当我们在进行数据库的运维工作时,很多时候会出现主从数据不一致的故障,尤其是当我们的binlog格式没有选择row模式,当主库执行一些类似于replace select或者时间函数等不确定的随机函数时,会出现从库数据和主库数据不一样。复制线程同步的时候就会报错,运营人员抽取数据就不会准确,尤其是对数据的一致性和安全性较高的金融公司。这个时候我们就要借助percona公司的pt工具来进行处理,pt-table-checksum和pt-table-sync分别检验master-slave的数据不一致并修复,避免了人工分析并筛选binlog日志进行修复的繁琐。但是对于pt工具,版本之间的差异还是比较大,尤其是pt工具的3.0.4版本并不能很好的检测出来,故而分享这个坑给诸位一线人员。
首先我们要熟悉pt工具的运行机制?
pt-table-checksum针对的binlog_format=statement的格式,根据pt-table-checksum的原理,它在执行的时候,没有将会话级别的binlog_format=statement设置成功,那我们只能手动将动态参数binlog_format设置为statement模式。只有在statement格式下才能进行,因为两边要计算CRC32,计算完后再把主上的master_crc、master_cnt更新到从库,最后在从库对比master和this相关列,也就是说从库不会去计算所谓的CRC32,它直接完整copy主库的checksums的所有内容。pt-table-checksum 3.0.4在执行时缺少SET@@binlog_format='STATEMENT',建议不要使用。
1、本次分享的Linux版本、pt工具版本、数据库实例、binlog_format的值如下
[root@172-16-3-190 we_ops_admin]# cat /etc/RedHat-release
CentOS release 6.8 (Final)
[root@172-16-3-190 we_ops_admin]# /opt/app/mysql_3309/bin/mysqladmin --version
/opt/app/mysql_3309/bin/mysqladmin Ver 8.42 Distrib 5.6.20-68.0, for Linux on x86_64
[root@172-16-3-190 we_ops_admin]# pt-table-checksum --version
pt-table-checksum 3.0.4
master1:172.16.3.190 basedir:/opt/app/mysql_3309/ datadir:/opt/app/mysql_3309/data port:3309
slave1:172.16.3.189 basedir:/opt/app/mysql_3309/ datadir:/opt/app/mysql_3309/data port:3309
master&slave:binlog_format=mixed
2、构造主从的数据差异,人为造成主从数据 不一致。这个过程就不概述了,数据模拟的过程大家都会操作。
----测试表aa结构
CREATE TABLE `aa` (
`aa` varchar(1) DEFAULT '',
`bb` varchar(1) DEFAULT NULL,
`id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
----master上表数据
mysql> select * from aa;
+------+------+----+
| aa | bb | id |
+------+------+----+
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 5 | 2 | 5 |
+------+------+----+
3 rows in set (0.00 sec)
----slave上表数据
mysql> select * from aa;
+------+------+----+
| aa | bb | id |
+------+------+----+
| 2 | 2 | 2 |
| 4 | 4 | 4 |
| 5 | 5 | 5 |
+------+------+----+
3 rows in set (0.00 sec)
3、利用pt工具检测差异
1)创建一个用户,可以访问master和slave,master上执行如下的创建用户命令。构造master-slave的差异环境,slave同步master数据后,人为修改slave数据使得不一致。
1 grant all privileges on *.* to 'checksums'@'172.16.%.%' identified by 'checksums'
2 Query OK, 0 rows affected (0.00 sec)
2)pt-table-checksum检测差异,并写入差异到checksums表中,master上执行如下命令。
1 [root@172-16-3-190 we_ops_admin]# /usr/bin/pt-table-checksum --create-replicate-table --replicate=ceshi.checksums --nocheck-replication-filters --nocheck-binlog-format --recursion-method=processlist --databases=ceshi --user=checksums --password=checksums -h172.16.3.190 --socket=/opt/app/mysql_3309/tmp/mysql.sock --port=3309
2 TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE
3 01-30T10:26:44 0 0 3 1 0 0.042 ceshi.aa
DIFFS=0表示没有差异数据。实际上主从数据不一致,我们已经加入了参数--nocheck-binlog-format,这里却没有检测出来。为什么没有检测出来呢?根据pt的执行机制,那到底是那一步出现问题了呢,有一种很挫的方法,仅仅是为了看差异结果(生产环境勿用),执行pt-table-checksum前,在主上 set global binlog_format='STATEMENT'。
master上执行
mysql> set @@global.binlog_format=statement;
Query OK, 0 rows affected (0.00 sec)
slave上执行
mysql> set @@global.binlog_format=statement;
Query OK, 0 rows affected (0.00 sec)