アクティブな読み取りと書き込みを行うライブシステムでmysqldumpを実行する最も安全な方法は?


78

これが本当かどうかはわかりませんが、Linuxで次のコマンドを実行すると読んだことを覚えています

mysqldump -u username -p database_name > backup_db.sql

データベースに対して読み取りおよび書き込みが行われている間、ダンプにはエラーが含まれる場合があります。

mysqldumpこれが稼働中のシステムで安全に実行されるようにするためのコマンドに特定のオプションはありますか?数秒間ユーザーの読み取り/書き込みを無効にしても問題ありません(データベース<50MB)

回答:


82

すべてのデータはInnoDBです

これにより、データの正確なポイントインタイムスナップショットが得られます。

mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql

--single-transaction変更を受信しながら、ダンプがチェックポイントの前にすべてのデータをキャプチャできるようにするチェックポイントを生成します。これらの着信変更はダンプの一部にはなりません。これにより、すべてのテーブルで同じポイントインタイムが保証されます。

--routines すべてのストアドプロシージャとストアド関数をダンプします

--triggers それらを持つ各テーブルのすべてのトリガーをダンプします

すべてのデータはMyISAMまたはInnoDB / MyISAMの混合です

グローバル読み取りロックを課し、mysqldumpを実行し、グローバルロックを解除する必要があります。

mysql -uuser -ppass -Ae"FLUSH TABLES WITH READ LOCK; SELECT SLEEP(86400)" &
sleep 5
mysql -uuser -ppass -ANe"SHOW PROCESSLIST" | grep "SELECT SLEEP(86400)" > /tmp/proclist.txt
SLEEP_ID=`cat /tmp/proclist.txt | awk '{print $1}'`
echo "KILL ${SLEEP_ID};" > /tmp/kill_sleep.sql
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql
mysql -uuser -ppass -A < /tmp/kill_sleep.sql

試してみる !!!

更新2012-06-22 08:12 EDT

合計データが50 MB未満であるため、別のオプションがあります。バックグラウンドでSLEEPコマンドを起動して86400秒(その24時間)グローバル読み取りロックを保持し、プロセスIDを取得して外部で強制終了する代わりに、OSではなくmysqlで5秒のタイムアウトを設定してみましょう。

SLEEP_TIMEOUT=5
SQLSTMT="FLUSH TABLES WITH READ LOCK; SELECT SLEEP(${SLEEP_TIMEOUT})"
mysql -uuser -ppass -Ae"${SQLSTMT}" &
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql

これは、非常に小規模なデータベース向けの、よりクリーンでシンプルなアプローチです。


1
5秒は単なる予防措置です。より低い値を試すことができます。
RolandoMySQLDBA

1
ローランド- ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query予想されるエラーメッセージは?
user784637

1
すべてのMySQLデータがmysqldumpに出力されましたか?
RolandoMySQLDBA

1
エラーメッセージについてはわかりません。これは推測に過ぎませんが、2行目のスクリプトで説明したユーザー定義のSLEEP関数呼び出しを強制終了する1行のスクリプトから得られた可能性があります。
RolandoMySQLDBA

1
私の新しい提案を試して、それがうまくいくかどうかを確認してください。うまくいけば、エラーメッセージは表示されません。
RolandoMySQLDBA


1

テーブルをロックするダウンタイムなしでMyISAMまたは混合テーブルに対してこれを実行する場合は、スレーブデータベースをセットアップして、そこからスナップショットを取得できます。残念ながら、スレーブデータベースをセットアップすると、ライブデータベースをエクスポートするためのダウンタイムが発生しますが、実行されると、そのテーブルをロックし、他の人が説明した方法を使用してエクスポートできるはずです。これが発生すると、マスターより遅れますが、マスターがテーブルを更新するのを止めず、バックアップが完了するとすぐに追いつきます。


1

ここに私がそれをした方法があります。を使用するため、すべての場合に機能するはず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;。レプリケーションスレーブを作成するには、作成したダンプの正確な状態(データベースのロックを解除する前)でバイナリログの位置を取得する必要があるためです。

1

:「読み取り専用スレーブでバックアップシナリオ2」MySQLの公式ドキュメントの提案は、あなたがマスター「M1」のデータベースとに記述されているスレーブ「S1」データベースが必要ということです それを作ることにより、マスタまたはスレーブのバックアップを読み取り専用

スレーブデータベースを読み取り専用に設定し、thを実行する必要があります


0

非常に大きなMYISAMテーブルがあり、ロックせずにテーブルをダンプし、サーバーの高負荷を避ける必要がある場合、次のスクリプトを使用できます。

#!/bin/sh

my_user="user"
my_password="password"
my_db="vpn"
my_table="traffic"
my_step=100000

read -p "Dumping table ${my_db}.${my_table} to ${my_table}.sql?" yn
case $yn in
    [Yy]* ) break;;
    * ) echo "User cancel."; exit;;
esac

my_count=$(mysql $my_db -u $my_user -p$my_password -se "SELECT count(*) FROM $my_table")
my_count=$(($my_count + 0))

if [ ! $my_count ]
then
    echo "No records found"
    exit
fi

echo "Records in table ${my_db}.${my_table}: ${my_count}"

echo "" > $my_table.sql

max_progress=60

for (( limit=0; limit<=$my_count; limit+=$my_step )); do
    progress=$((max_progress * ( limit + my_step) / my_count))

    echo -ne "Dumping ["
    for ((i=0; i<$progress; i ++)); do
        echo -ne "#"
    done
    for ((; i<$max_progress; i ++)); do
        echo -ne "."
    done

    mysqldump -u $my_user -p$my_password --complete-insert --no-create-info --opt --where="1 limit $limit , $my_step" $my_db $my_table >> $my_table.sql
    echo "" >> $my_table.sql

    echo -ne "] $((100 * ( limit + my_step ) / my_count)) %"
    echo -ne "\r"

    sleep 1

done

echo -ne "\n"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.