2012-12-27 6 views
9

mysqldumpを実行するバックアップシェルスクリプトを作成します。どのように1つのmysqlデータベース内のすべてのテーブルをロックするには?

mysqldump -u$BACKUP_USER -p$BACKUP_PASS --flush-logs --lock-tables $DB_NAME > $SQL_FILE 

My dbのストレージENGINEはMyISAMです。だから私は--single-transactionオプションを使用することはできません。 --lock-tablesは、mysqldumpの進行中に1つのテーブルだけをロックします。 私のMySQLインスタンスには多くのデータベースがありますが、私は--lock-all-tablesを使用したくないので、私のサーバーで実行されているすべてのデータベースをロックします。 それで、どのように私はそれをダンプすることができますので、sametimeでONEのMySQLデータベースのすべてのテーブルをロックするには?

+1

'--lock-tables'は、ダンプする前にすべてのテーブルをダンプする必要があります。あなたはそれがそうではないと思いますか? – cdhowie

+0

私はmysqldumpで--lock-tablesを使うとmysql 5.1でテストをしましたが、$ DB_NAMEデータベースのテーブルにデータを挿入することはできます。 – KeepZero

答えて

4

このオプションを調べる必要があります。

FLUSH TABLES WITH READ LOCK

開いているすべてのテーブルを閉じ、グローバルリードロックを持つすべてのデータベースのすべてのテーブルをロックします。これは...

http://dev.mysql.com/doc/refman/5.0/en/flush.html

+0

'FLUSH TABLES WITH READ LOCK' – Benjamin

+0

これは、単一データベース内のテーブルだけでなく、*グローバル*読み取りロックを発行します。 –

6

そう遠くないことにより、きれいなソリューション、バックアップを取得するには非常に便利な方法ですが、これは動作します。私は同じ必要性を持っていました。私の解決策は、あなたの変数名と一致するように少し修正されました。私はあなたがLinux上でMySQLを実行していると仮定しています。これはシェルのBASHセマンティクスにかなり依存しているためです。 Windowsの場合、これはうまくいきません。

# Mysql script to lock all tables in one DB 
# (such as to get a consistent export dump of one database) 

MYSQLCMD="mysql -u$BACKUP_USER -p$BACKUP_PASS -A" 

function lock_db { 
    [ -e "/tmp/mysql-db-lock-${1}" ] && rm "/tmp/mysql-db-lock-${1}" 
    mkfifo "/tmp/mysql-db-lock-${1}" 
    (
    (
     echo "SELECT CONCAT('LOCK TABLES ' 
      , GROUP_CONCAT(CONCAT('\`',table_name,'\`'),' WRITE') 
      , ';' 
      ) AS \"-- Statement to lock tables\" 
     FROM information_schema.tables 
     WHERE table_schema='${1}' 
     ORDER BY table_name; 
     " | $MYSQLCMD 
     echo "\! cat '/tmp/mysql-db-lock-${1}' >/dev/null" 
     echo 'UNLOCK TABLES;' 
    ) | $MYSQLCMD -D"${1}" 
    rm "/tmp/mysql-db-lock-${1}" 
) & 
} 

function unlock_db { 
    >"/tmp/mysql-db-lock-${1}" 
} 

# Lock one database, all tables 
lock_db $DB_NAME 

# Verify locks have been placed 
echo "SHOW OPEN TABLES WHERE in_use != 0" | $MYSQLCMD 

# Do whatever here that you needed the locked db for 
mysqldump -u$BACKUP_USER -p$BACKUP_PASS $DB_NAME > $SQL_FILE 

# Release locks 
unlock_db $DB_NAME 

# Verify locks released 
echo "SHOW OPEN TABLES WHERE in_use != 0" | $MYSQLCMD 
+0

データベースから各テーブルを選択します。これは、 "FLUSH TABLES WITH READ LOCK"よりも優れていますが、すべてのデータベースのすべてのテーブルをロックしますが、あなたのソリューションは(少なくとも私のために)たくさんのテーブルを含むデータベースで失敗するようです。 "FLUSH TABLES WITH READ LOCK"(すべてのデータベースのすべてのテーブルをロック)を使用して変更し、最初のパイプを$ MYSQLCMDに削除しました。 – OderWat

+0

更新:私は "SET SESSION group_concat_max_len = 8192;"を使用しました。あなたの最初のエコーの前にそれが最初に問題を引き起こしていたからです!あなたのクールなスクリプトのTY! – OderWat

+0

あなたが好きなら、アップしてください。 –

2

ここで私はそれをしました。 FLUSH TABLES WITH READ LOCKを使用しているため、すべての場合に有効です。

#!/bin/bash 

DB=example 
DUMP_FILE=export.sql 

# Lock the database and sleep in background task 
mysql -uroot -proot $DB -e "FLUSH TABLES WITH READ LOCK; DO SLEEP(3600);" & 
sleep 3 

# Export the database while it is locked 
mysqldump -uroot -proot --opt $DB > $DUMP_FILE 

# When finished, kill the previous background task to unlock 
kill $! 2>/dev/null 
wait $! 2>/dev/null 

echo "Finished export, and unlocked !" 

シェルsleepコマンドだけのmysqldumpが始まる前に、MySQLのロックコマンドを実行しているバックグラウンドタスクが実行されていることを確認することです。あなたは1秒にそれを減らすことができ、それはまだうまくいくはずです。それを30秒間に増やし、30秒間別のクライアントからのテーブルに値を挿入しようとすると、ロックされていることがわかります。

2つの利点は、代わりにmysqldumpオプション--single-transaction--lock-tablesを使用するのでは、このマニュアル背景のロックを使用してあります。

  1. あなたはMyISAMテーブル/ InnoDBテーブルを混在している場合、これは、すべてをロックします。
  2. 同じロック期間中にmysqldumpに加えて他のコマンドを実行することができます。たとえば、マスターノードでレプリケーションを設定する場合には、SHOW MASTER STATUS;で作成したダンプの正確な状態(データベースのロックを解除する前)でバイナリログの位置を取得する必要があるため、レプリケーションスレーブを作成できるので便利です。
+0

これは、単一のデータベースをバックアップしている場合でも、すべてのデータベースで*グローバル*ロックを発行します。 –

関連する問題