レプリケーションの問題でよくある10パターン。
1) セッションのみで有効なバイナリログ
sql_log_bin = 0
を設定すると、そのセッション内でバイナリログを無効にできる。つまり、マスタのセッション内で実行したDMLやDDLは、スレーブにはレプリケーションされない。
マスタでバイナリログをオフにする。
mysql> set sql_log_bin = 0 ;
Query OK, 0 rows affected (0.00 sec)
reptestデータベースにテーブルを作成してみる(マスタ上で実行)。
mysql> create table reptest(ID int) ;
Query OK, 0 rows affected (0.01 sec)
mysql> show tables ;
+-------------------+
| Tables_in_reptest |
+-------------------+
| reptest |
+-------------------+
1 row in set (0.00 sec)
スレーブで確認してみると、テーブルは作成されていない。
mysql> use reptest ;
Database changed
mysql> show tables ;
Empty set (0.00 sec)
2) スレーブの直接更新
アプリケーションからスレーブを直接更新してしまうと、マスタとスレーブは同期しなくなってしまう。スレーブをread_only
に設定しておくのは良い習慣と言えるが、DBAが直接スレーブを更新してしまうのは防げないかもしれない。
3) バイナリログの破損
以下は、壊れたバイナリログの例。
# Position Timestamp Type Master ID Size Master Pos Flags
# 4 51 2e 30 4d 0f 01 00 00 00 66 00 00 00 6a 00 00 00 00 00
# 17 04 00 35 2e 32 2e 34 2d 4d 61 72 69 61 44 42 2d |..5.2.4.MariaDB.|
# 27 6d 61 72 69 61 64 62 39 34 2d 6c 6f 67 00 00 00 |mariadb94.log...|
# 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
# 47 00 00 00 00 00 00 00 00 13 38 0d 00 08 00 12 00 |.........8......|
# 57 04 04 04 04 12 00 00 53 00 04 1a 08 00 00 00 08 |.......S........|
# 67 08 08 02 |...|
# Start: binlog v 4, server v 5.2.4-MariaDB-mariadb94-log created 110114 6:06:57
BINLOG '
US4wTQ8BAAAAZgAAAGoAAAAAAAQANS4yLjQtTWFyaWFEQi1tYXJpYWRiOTQtbG9nAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC
'/*!*/;
# at 48954702
このような場合は、以下のいずれかの方法で修正ができるだろう。
適切な(通常は壊れたバイナリログの次)ポジションを指定して
change master
コマンドを実行して、レプリケーションを再開する。change master to master_log_position = next_pos; start slave;
場合によっては、
pt-table-checksum
やpt-table-sync
などのコマンドを使って、スレーブを同期する。上の2つとも失敗した場合には、データベースをリストアする。
4) リレーログの破損
ネットワークやデータの送信時の問題で、リレーログの破損が起きる場合がある。mysqlbinlog
コマンドを使って、破損の直前のレプリケーション状態を特定し、change master
コマンドで適切なポジションからレプリケーションを再開させる。
STOP SLAVE;
CHANGE MASTER TO
MASTER_HOST='< master-host ip or DNS >',
MASTER_PORT=3306,
MASTER_USER='< usernmae >',
MASTER_PASSWORD='< password >',
MASTER_LOG_FILE='< MMMM >',
MASTER_LOG_POS=< PPPP >;START SLAVE;
5) バイナリログの削除やパージ
マスタのバイナリログをパージしてしまう前に、スレーブでそのログが適用済みかを確認しよう。purge binary logs
コマンドをマスタで実行する時には、特に注意しなければならない。
6) 安全でないレプリケーション(確定的でない関数の使用)
以下が、確定的でない関数の例だ。これらの関数は、マスタとスレーブで違う結果を返す可能性がある。
FOUND_ROWS(), GET_LOCK(), IS_FREE_LOCK(), IS_USED_LOCK(), LOAD_FILE(), MASTER_POS_WAIT(), PASSWORD(), RAND(), RELEASE_LOCK(), ROW_COUNT(), SESSION_USER(), SLEEP(), SYSDATE(), SYSTEM_USER(), USER(), UUID(), UUID_SHORT()
例を見てみよう。マスタで以下のように実行する。
mysql> insert into timetable values(sysdate()) ;
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from timetable ;
+---------------------+
| tvalue |
+---------------------+
| 2014-09-21 14:56:05 |
+---------------------+
1 row in set (0.00 sec)
スレーブでは、違う値になり得る。
mysql> select * from timetable ;
+---------------------+
| tvalue |
+---------------------+
| 2014-09-21 14:56:02 |
+---------------------+
1 row in set (0.00 sec)
7) change master文の間違い
change master
の実行は注意が必要だ。間違ったバイナリログのポジションを指定してしまうと、実行されるべき文が抜けてしまう可能性がある。それ以外にも、skip global sql_slave_skip_counter
やreset slave
、reset master
なども注意を要する文だ。
8) binlog-do-db、binlog-ignore-db、replicate-do-db、replicate-ignore-dbの影響
これらの設定オプションは、レプリケーションするテーブルを選択するのに使う。しかし、間違って設定されてしまうとデータのずれの原因になり得る。
9) レプリケーション関連のバグ
以下は、レプリケーションを破壊する原因になり得るバグ(現在も有効で未修正のもの)だ。
- http://bugs.mysql.com/bug.php?id=72556
- http://bugs.mysql.com/bug.php?id=71859
- http://bugs.mysql.com/bug.php?id=70832
- http://bugs.mysql.com/bug.php?id=71111
10) マスタのクラッシュ
マスタサーバののクラッシュは、レプリケーションエラーを引き起こす事がある。sync_binlog
変数が役に立つかもしれない。
(MySQLリファレンスマニュアル 17.1.3.4 Binary Log Options and Variables)
この変数の値が0以上の場合、バイナリログへの書き込みをsync_binlog回行うごとにMySQLサーバはバイナリログをディスクに同期します(fdatasync()を使用)。 自動コミットが有効な時には1文ごとにバイナリログへの書き込みが行われ、そうでない時にはトランザクションごとに書き込みが行われます。 sync_binlogのデフォルト値は0で、この場合(MySQLサーバは)ディスクへの同期は行わずOSに任せるので、他のファイルと同じようにその時その時でバイナリログの中身もディスクに書き出されます。 1に設定しておくと、クラッシュの際にもバイナリログ内の最大1つの文あるいはトランザクションしか失われないので、最も安全です。 しかし、動作的には最も遅くなります(ディスクへの同期を非常に高速化してくれるバッテリ付きのキャッシュ搭載のディスク以外の場合)。