//
pt-table-checksum命令检查数据一致性
//
今天上班遇到了一个主从复制失败的问题,问题的表现是从库复制报错,最终通过修改参数slave_exec_mode的方法暂时解决了问题。关于这个参数,之前写过一篇文章进行描述,这里给出链接:
复制虽然修复了,主从的数据是否一致?这个可能还是个问题,于是我想到了pt-table-checksum这个工具,这个工具之前用的比较少,今天再来总结总结这个工具的用法。
pt-table-checksum主要是用来检测主从的数据一致性的,它一般在主库上执行,使用到的常见参数和输出分别如下:
01
常用参数
--replicate:将查到的数据不一致的结果保存在某个表中。(一般制定为当前数据库里面的表)
--nocheck-replication-filters:不检查复制过滤器
--replicate-check:检测复制中的不一致,为默认选项,可以不指定。可设置为--no-replicate-check,从而表示不检测
--replicate-check-only:检测复制中的不一致,结果集中仅显示不一致的表,没有这个参数的话,会将结果集中一致的表也显示出来
--no-check-binlog-format:不检测主从的binlog格式是否一致
--recursion-method:检测从库的方法,默认是使用show processlist,还可以使用show slave hosts
--databases:数据库
--tables:要检测的表,如果没有指定,则检测数据库下面的所有表
--password:密码
--port:端口
--host:主机IP
02
命令测试
在MySQL版本8.0.19、pt工具版本3.0.4、MySQL binlog_format=row模式下,进行测试结果如下:
# 主库数据
mysql--dba_admin@127.0.0.1:test 20:10:59>>select * from test_data;
+----+------+------+---------------------+
| id | oid | name | cdate |
+----+------+------+---------------------+
| 8 | 8 | hh | 2020-05-27 18:00:00 |
| 11 | 12 | yeyz | 2020-07-08 00:00:00 |
+----+------+------+---------------------+
2 rows in set (0.00 sec)
# 从库数据
mysql--dba_admin@127.0.0.1:test 20:15:29>>select * from test_data;
+----+------+------+---------------------+
| id | oid | name | cdate |
+----+------+------+---------------------+
| 8 | 8 | hh | 2020-05-27 18:00:00 |
| 10 | 15 | ll | 2020-06-03 00:00:00 |
+----+------+------+---------------------+
2 rows in set (0.00 sec)
[dba_mysql ~]$ /usr/local/mysql_tools/percona-toolkit-3.0.4/bin/pt-table-checksum --replicate=test.yeyz --nocheck-replication-filters --no-check-binlog-format --databases=test --replicate-check --recursion-method=processlist h=127.0.0.1,u=dba_admin,p=xxxxxx,P=4307
TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE
07-08T20:34:26 0 0 2 1 0 0.012 test.test_data
先对输出结果做一个解释:
TS :完成检查的时间。
ERRORS :检查时候发生错误和警告的数量。
DIFFS :0表示一致,1表示不一致。当指定--no-replicate-check时,会一直为0,当指定--replicate-check-only仅仅显示数据不一致的表信息。
ROWS :表的行数。
CHUNKS :被划分到表中的块的数目。
SKIPPED :由于错误或警告或过大,则跳过块的数目。
TIME :执行的时间。
TABLE :被检查的表名。
可以看到,最后的结果中检测行数是2,DIFFS是0,也就是没有检测出来不同,这和我们的预期不符。继续查看percona官方文档,发现该命令有如下限制。
03
限制
1、该工具需要主库是基于statement的binlog,如果是基于row模式的,则会进行binlog格式修改,但是由于MySQL中对binlog格式的修改不能应用在当前的session中,所以对binlog格式的修改不会成功。此时需要手工修改binlog的格式。set global binlog_format=statement.
2、当主从表结构不一致或者主从数据库不一致的时候,该工具没办法检测。例如数据库没有写入,然后在从库上删除了数据库,此时主库有db,从库无db,则检测会失败。
04
重新测试
将主库和从库的binlog格式都改为statement格式,然后测试该工具的执行结果:
[dba_mysql ~]$ /usr/local/mysql_tools/percona-toolkit-3.0.4/bin/pt-table-checksum --replicate=test.yeyz --nocheck-replication-filters --no-check-binlog-format --databases=test --replicate-check --recursion-method=processlist h=127.0.0.1,u=dba_admin,p=xxxxxx,P=4307
TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE
07-08T20:37:55 0 1 2 1 0 0.014 test.test_data
可以看到,已经检测出来主库和从库的不同了。在上面的命令中,我们制定了--tables参数,如果不指定--tables参数,那么会检测该db下面的所有表是否一致。
再来看看我们--replicate参数下面制定的表里面的结果:
# 主库结果
mysql >>select * from test.yeyz;
+------+-----------+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+
| db | tbl | chunk | chunk_time | chunk_index | lower_boundary | upper_boundary | this_crc | this_cnt | master_crc | master_cnt | ts |
+------+-----------+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+
| test | test_data | 1 | 0.000697 | NULL | NULL | NULL | 7203812e | 2 | 7203812e | 2 | 2020-07-08 21:38:59 |
+------+-----------+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+
1 row in set (0.00 sec)
#从库结果
mysql >>select * from test.yeyz;
+------+-----------+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+
| db | tbl | chunk | chunk_time | chunk_index | lower_boundary | upper_boundary | this_crc | this_cnt | master_crc | master_cnt | ts |
+------+-----------+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+
| test | test_data | 1 | 0.000697 | NULL | NULL | NULL | 24ba472d | 2 | 7203812e | 2 | 2020-07-08 21:38:59 |
+------+-----------+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+
1 row in set (0.00 sec)
可以看到,从库和master的数据是不一致的。
05
数据不一致如何修复?
可以利用pt-table-sync来进行修复。
该工具可以使用--sync-to-master参数结合--print参数来打印出来修复从库所需要的SQL文本,然后再从库上执行这些SQL脚本修复即可。
关于pt-table-sync可以参看percona官方文档:
https://www.percona.com/doc/percona-toolkit/LATEST/pt-table-sync.html
由于在binlog_format=row模式下无法使用,pt-table-checksum工具,所以这个pt-table-sync工具我就没有测试,有兴趣的同学可以自行了结下。