MySQLではレプリケーション機能を使って容易にデータベースを複製することができますが、
今回はそのような時にデータを比較するやり方をいくつか説明します。なお、
CHECKSUM TABLE構文によるテーブルの比較
MySQLではテーブル保守のためのステートメントとして、
CHECKSUM TABLE構文は、
また、
> > CHECKSUM TABLE t1,t2,t3,t4; +-------+------------+ | Table | Checksum | +-------+------------+ | d1.t1 | 1778287754 | | d1.t2 | 1591722216 | | d1.t3 | 0 | | d1.t4 | NULL | +-------+------------+ 4 rows in set, 1 warning (0.00 sec)
mysqldbcompareによるテーブルの比較
MySQL Utilitiesにmysqldbcompareという2つのデータベースを比較するツールがあります。このツールは2つのデータベースからデータを比較し、
今、
localhost:3307 > INSERT INTO t3 VALUES (10, 'dummy_data', 1, now()); Query OK, 1 row affected (0.01 sec) localhost:3307 > CREATE VIEW v_t2 AS SELECT id, name FROM t2; Query OK, 0 rows affected (0.01 sec)
この状態mysqldbcompareを実行してみます。mysqldbcompareは、
mysqldbcompare --server1 <user>:<password>@<host>:<port> --server2 <user>:<password>@<host>:<port> <比較したいserver1のdatabase名>:<比較したいserver2のdatabase名> <オプション>$ mysqldbcompare --server1 root:password1@localhost:3306 --server2 root:password2@localhost:3307 d1:d1 --run-all-tests # WARNING: Using a password on the command line interface can be insecure. # server1 on localhost: ... connected. # server2 on localhost: ... connected. # Checking databases d1 on server1 and d1 on server2 # # WARNING: Objects in server2.d1 but not in server1.d1: # VIEW: v_t2 # # Defn Row Data # Type Object Name Diff Count Check # ------------------------------------------------------------------------- # TABLE t1 pass pass - # - Compare table checksum pass # TABLE t2 pass pass - # - Compare table checksum pass # TABLE t3 pass FAIL - # - Compare table checksum FAIL # - Find row differences FAIL # # Row counts are not the same among `d1`.`t3` and `d1`.`t3`. # # Rows in `d1`.`t3` not in `d1`.`t3` +-----+-------------+-----+----------------------+ | id | c1 | c2 | c3 | +-----+-------------+-----+----------------------+ | 10 | dummy_data | 1 | 2018-03-27 21:28:55 | +-----+-------------+-----+----------------------+ # Database consistency check failed. # # ...done
比較した結果、
また、
$ mysqldbcompare --server1 root:password1@localhost:3306 --server2 root:password2@localhost:3307 d1:d1 --run-all-tests --difftype=sql
# WARNING: Using a password on the command line interface can be insecure.
# server1 on localhost: ... connected.
# server2 on localhost: ... connected.
# Checking databases d1 on server1 and d1 on server2
#
# WARNING: Objects in server2.d1 but not in server1.d1:
#         VIEW: v_t2
#
#                                                   Defn    Row     Data
# Type      Object Name                             Diff    Count   Check
# -------------------------------------------------------------------------
# TABLE     t1                                      pass    pass    -
#           - Compare table checksum                                pass
# TABLE     t2                                      pass    pass    -
#           - Compare table checksum                                pass
# TABLE     t3                                      pass    FAIL    -
#           - Compare table checksum                                FAIL
#           - Find row differences                                  FAIL
#
# Row counts are not the same among `d1`.`t3` and `d1`.`t3`.
#
# Transformation for --changes-for=server1:
#
INSERT INTO `d1`.`t3` (`id`, `c1`, `c2`, `c3`) VALUES('10', 'dummy_data', '1', '2018-03-27 21:28:55');
# Database consistency check failed.
#
# ...done
今度はSQL形式で差分を取得することができました。このように、
詳細な使い方については、
pt-table-checksumを利用してデータを比較する
Percona Toolkitの中にpt-table-checksumというツールがあります。pt-table-checksumが今まで紹介したツールと違う点として、
DSNを使ったpt-table-checksumのデータ比較
デフォルトではレプリケーション先の確認として、
今回はマスターのmysqlデータベースにdsnsテーブルを作成し、
> CREATE TABLE mysql.dsns (
    -> id int(11) NOT NULL AUTO_INCREMENT,
    -> parent_id int(11) DEFAULT NULL,
    -> dsn varchar(255) NOT NULL,
    -> PRIMARY KEY (id)
    -> );
Query OK, 0 rows affected (0.02 sec)
    
> INSERT INTO mysql.dsns VALUES (1,null,'h=127.0.0.1,P=3307,u=root,p=password2');
Query OK, 1 row affected (0.00 sec)
pt-table-checksumを実施するときは、
$ pt-table-checksum  --host 127.0.0.1 --port 3306 --user root --password passwod1 --recursion-method="dsn=D=mysql,t=dsns" --databases d1
            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
03-29T01:36:57      0      0        3       1       0   0.012 d1.t1
03-29T01:36:57      0      0      100       1       0   0.263 d1.t2
03-29T01:36:57      0      1        0       1       0   0.013 d1.t3
データ比較によって、
replicateオプションを利用してpt-table-checksumのデータ比較を実施する
DSNを利用せずにpt-table-checksumを実施する場合は、
pt-table-checksum  --host <host名> --port <port> --user <user名> --password <password> --replicate <比較結果のテーブル名> --database <比較するデータベース名>今回はreplicateオプションを利用してmysqlデータベースにpt_
$ pt-table-checksum  --host 127.0.0.1 --port 3306 --user root --password password1 --replicate mysql.pt_tcs --databases d1
Diffs cannot be detected because no slaves were found.  Please read the --recursion-method documentation for information.
            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
03-28T09:51:44      0      0        3       1       0   0.013 d1.t1
03-28T09:51:44      0      0      100       1       0   0.009 d1.t2
03-28T09:51:44      0      0        0       1       0   0.009 d1.t3
> DESC mysql.pt_tcs;
+----------------+--------------+------+-----+-------------------+-----------------------------+
| Field          | Type         | Null | Key | Default           | Extra                       |
+----------------+--------------+------+-----+-------------------+-----------------------------+
| db             | char(64)     | NO   | PRI | NULL              |                             |
| tbl            | char(64)     | NO   | PRI | NULL              |                             |
| chunk          | int(11)      | NO   | PRI | NULL              |                             |
| chunk_time     | float        | YES  |     | NULL              |                             |
| chunk_index    | varchar(200) | YES  |     | NULL              |                             |
| lower_boundary | text         | YES  |     | NULL              |                             |
| upper_boundary | text         | YES  |     | NULL              |                             |
| this_crc       | char(40)     | NO   |     | NULL              |                             |
| this_cnt       | int(11)      | NO   |     | NULL              |                             |
| master_crc     | char(40)     | YES  |     | NULL              |                             |
| master_cnt     | int(11)      | YES  |     | NULL              |                             |
| ts             | timestamp    | NO   | MUL | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+----------------+--------------+------+-----+-------------------+-----------------------------+
こちらのmaster_
> SELECT * FROM mysql.pt_tcs WHERE this_crc <> master_crc; +----+-----+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+ | db | tbl | chunk | chunk_time | chunk_index | lower_boundary | upper_boundary | this_crc | this_cnt | master_crc | master_cnt | ts | +----+-----+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+ | d1 | t3 | 1 | 0.002825 | NULL | NULL | NULL | dbc6a82c | 1 | 0 | 0 | 2018-03-29 01:47:28 | +----+-----+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+ 1 rows in set (0.00 sec)
t3テーブルに差分があることが確認できました。
pt-table-checksumについては他にもさまざまなオプションがあります。詳細な使い方についてはpercona-toolkitのpt-table-checksumの公式マニュアルをご確認ください。
まとめ
今回はデータベースの比較方法として3つの方法を紹介しました。
レプリケーションを組んだ状態であればpt-table-checksumを利用し、