今回は以前話した、MySQLデータベースのレプリカの話の続きです。
前回はデータベースのレプリカの説明をしましたが、本当にマスターのデータベースと同期しているの?とすぐに疑います。
チェックしてみましょう!
調べると、checksum table
というMySQLコマンドが使えるらしい。チェックサムはある計算式をデータに適用してユニークな数を出力するものです。
mysql> use larajapan; Database changed mysql> checksum table migrations, password_resets, users; +---------------------------+------------+ | Table | Checksum | +---------------------------+------------+ | larajapan.migrations | 269719583 | | larajapan.password_resets | 3233767743 | | larajapan.users | 669472749 | +---------------------------+------------+ 3 rows in set (0.00 sec)
実行してみるとかなりな速さで結果を出してくれます。私のテストでは500万レコード数もあるテーブルでたったの16秒!
これを、マスターとそのレプリカで、すべてのテーブルに対して実行して比較すれば良いですね。しかし、実際に使用されているDBでは、常に新しいレコードは追加される、更新はある。。。と考えると、ある1時点で両者のデータを比較するのは複雑な作業に見えてきます。
そこで見つけたのが、perconaのツール。perconaはかなり昔からMySQLなどのオープンソースのデータベースの管理をサービスとしている会社です。
準備
AWS EC2では、以下でインストールできます。
$ sudo yum install http://www.percona.com/downloads/percona-release/redhat/0.1-6/percona-release-0.1-6.noarch.rpm
たくさんのツール(perlで書かれている)がインストールされますが、今回必要なツールはマスターとレプリカのデータの同期をチェックする以下のコマンドです。
しかし、このツール、オプションがたくさんあり、ある程度の準備も要る複雑なツールです。私も理解まで何回も何回も試行しました。特に、マスターのDBとレプリカのDBで、MySQLのユーザー名やパスワードが違うとその指定のためにコマンドラインが長くなり、実行にはスクリプトの作成をした方が良いです。
ちなみに、今回は、以前と同様に、マスターはEC2でのMySQL、レプリカは、AWSのRDSのMySQLという仮定です。もちろんレプリカのサーバーにはsshできないので、マスターで実行します。
準備として、以下のMySQLの情報を用意してください。
マスターのユーザー名
マスターのパスワード
レプリカのユーザー名
レプリカのパスワード
マスターやレプリカのMySQLユーザーは以下の権限が必要ですが、以下のように特別に作成しなくとも、通常はrootのような管理権限のあるユーザーで足ります。
mysql> GRANT SELECT ON larajapan.* TO 'checksum_user'@'%' IDENTIFIED BY 'checksum_password'; mysql> GRANT REPLICATION SLAVE,PROCESS,SUPER ON *.* TO `checksum_user`@'%'; mysql> GRANT ALL PRIVILEGES ON percona.* TO `checksum_user`@'%';
次に、ツールが出力するデータを保存するためのデータベース(percona)とテーブル(checksums)を作成します。
mysql> create databaser percona; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'databaser percona' at line 1 mysql> create database percona; Query OK, 1 row affected (0.00 sec) mysql> use percona Database changed mysql> CREATE TABLE checksums ( db CHAR(64) NOT NULL, tbl CHAR(64) NOT NULL, chunk INT NOT NULL, chunk_time FLOAT NULL, chunk_index VARCHAR(200) NULL, lower_boundary TEXT NULL, upper_boundary TEXT NULL, this_crc CHAR(40) NOT NULL, this_cnt INT NOT NULL, master_crc CHAR(40) NULL, master_cnt INT NULL, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (db, tbl, chunk), INDEX ts_db_tbl (ts, db, tbl) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; Query OK, 0 rows affected (0.01 sec)
マスターとレプリカの両方で作成が必要ですが、ツールの最初の実行でマスターでは自動的に作成されます。
実行
ここで、まず実行してみましょう。運が良ければここで以下のような出力となります。
$ pt-table-checksum -d larajapan -u checksum_user -p checksum_password --recursion-method processlist --no-check-binlog-format --no-check-replication-filters Checking if all tables can be checksummed ... Starting checksum ... TS ERRORS DIFFS ROWS DIFF_ROWS CHUNKS SKIPPED TIME TABLE 11-09T07:54:37 0 0 2 0 1 0 1.019 larajapan.migrations 11-09T07:54:37 0 0 1 0 1 0 0.017 larajapan.password_resets 11-09T07:54:37 0 0 5 0 1 0 0.014 larajapan.users
ERRORSとDIFFSの列、これが皆ゼロならマスターとレプリカは同期しています。心配なしです。
さて、どうしてレプリカのホスト情報をコマンドラインに入れていないのにレプリカのチェックが可能なのでしょう?
それは、--recursion-method processlist
の部分です(デフォルトでは、ここはprocesslist, hostsとなるのですが、私のトライではhostsの部分でエラーになりました)。
MySQLのshow processlistコマンドを実行すると、
mysql> show processlist; +-----+------------+-----------------------------------------------+--------------+-------------+-------+-----------------------------------------------------------------------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +-----+------------+-----------------------------------------------+--------------+-------------+-------+-----------------------------------------------------------------------+------------------+ | 2 | slave_user | ip-10-0-1-32.us-west-2.compute.internal:64617 | NULL | Binlog Dump | 14651 | Master has sent all binlog to slave; waiting for binlog to be updated | NULL | | 918 | root | localhost | NULL | Query | 0 | NULL | show processlist | | 919 | root | localhost | larajapan_wp | Sleep | 0 | | NULL | +-----+------------+-----------------------------------------------+--------------+-------------+-------+-----------------------------------------------------------------------+------------------+ 3 rows in set (0.00 sec)
レプリカのホスト情報が出て来るのでそれを利用しているのです。
また、ここでは、レプリカでのMySQLのユーザー名とパスワードは、マスターと同じと仮定しています。これが違うなら、
--slave-user admin --slave-password pass
の指定がコマンドラインで必要となります。
本当にチェックしている?
ひとまず成功したところで、本当に差分を出してくれるか興味あるところです。レプリカにおいて、情報変えてみましょう。
mysql> delete from users where id = 6; Query OK, 1 row affected (0.01 sec)
レプリカのusersのテーブルのレコードを1つ削除しました。
そして再度実行です。
$ pt-table-checksum -d larajapan -u checksum_user -p checksum_password --recursion-method processlist --no-check-binlog-format --no-check-replication-filters Checking if all tables can be checksummed ... Starting checksum ... TS ERRORS DIFFS ROWS DIFF_ROWS CHUNKS SKIPPED TIME TABLE 11-09T08:18:43 0 0 2 0 1 0 0.021 larajapan.migrations 11-09T08:18:43 0 0 1 0 1 0 0.017 larajapan.password_resets 11-09T08:18:43 0 1 5 0 1 0 0.019 larajapan.users
チェックしてくれましたね。DIFFSに1が表示されているのがそうです。
デバッグ
このコマンドラインでは、本当にたくさんのオプションがあるのでいろいろなチェックが可能なのですが、エラーが理解不可能なときは、以下のようにデバッグモードを使ってみるのが良いです。stderrに情報がたくさん出力されるので以下のようにファイルにキャプチャする必要あります。
$ PTDEBUG=1pt-table-checksum > FILE 2>&1
また、オプションのデフォルトも把握することも大事です。
$ pt-table-checksum --help
の実行でデフォルトの情報が得られます。
メルマガ購読の申し込みはこちらから。