Yakstは、海外の役立つブログ記事などを人力で翻訳して公開するプロジェクトです。
10年弱前投稿 修正あり

MySQLのレプリケーションでありがちな10の問題

レプリケーションに不整合が起きたり、切れてしまったりする際の、一般的な原因10個の仕組みと解決法。

原文
10 common replication problems (English)
翻訳依頼者
D98ee74ffe0fafbdc83b23907dda3665
翻訳者
D98ee74ffe0fafbdc83b23907dda3665 doublemarket
原著者への翻訳報告
未報告


レプリケーションの問題でよくある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

このような場合は、以下のいずれかの方法で修正ができるだろう。

  1. 適切な(通常は壊れたバイナリログの次)ポジションを指定してchange masterコマンドを実行して、レプリケーションを再開する。

    change master to master_log_position = next_pos;
    start slave;
    
  2. 場合によっては、pt-table-checksumpt-table-syncなどのコマンドを使って、スレーブを同期する。

  3. 上の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_counterreset slavereset masterなども注意を要する文だ。

8) binlog-do-db、binlog-ignore-db、replicate-do-db、replicate-ignore-dbの影響

これらの設定オプションは、レプリケーションするテーブルを選択するのに使う。しかし、間違って設定されてしまうとデータのずれの原因になり得る。

9) レプリケーション関連のバグ

以下は、レプリケーションを破壊する原因になり得るバグ(現在も有効で未修正のもの)だ。

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つの文あるいはトランザクションしか失われないので、最も安全です。 しかし、動作的には最も遅くなります(ディスクへの同期を非常に高速化してくれるバッテリ付きのキャッシュ搭載のディスク以外の場合)。

次の記事
MySQL 5.6でバイナリログへの書き込み失敗時にサーバを停止できるオプション
前の記事
MySQLの新しいデータディクショナリー

Feed small 記事フィード

新着記事Twitterアカウント