pt-table-sync修复主从不一致
pt-table-sync简介
顾名思义,它用来修复多个实例之间数据的不一致。它可以让主从的数据修复到最终一致,也可以使通过应用双写或多写的多个不相关的数据库实例修复到一致。同时它还内部集成了pt-table-checksum的校验功能,可以一边校验一边修复,也可以基于pt-table-checksum的计算结果来进行修复。
工作原理
1. 单行数据checksum值的计算
计算逻辑与pt-table-checksum一样,也是先检查表结构,并获取每一列的数据类型,把所有数据类型都转化为字符串,然后用concat_ws()函数进行连接,由此计算出该行的checksum值。checksum默认采用crc32计算。
2. 数据块checksum值的计算
同pt-table-checksum工具一样,pt-table-sync会智能分析表上的索引,然后把表的数据split成若干个chunk,计算的时候以chunk为单位。可以理解为把chunk内所有行的数据拼接起来,再计算crc32的值,即得到该chunk的checksum值。
3. 坏块检测和修复
前面两步,pt-table-sync与pt-table-checksum的算法和原理一样。再往下,就开始有所不同:
pt-table-checksum只是校验,所以它把checksum结果存储到统计表,然后把执行过的sql语句记录到binlog中,任务就算完成。语句级的复制把计算逻辑传递到从库,并在从库执行相同的计算。pt-table-checksum的算法本身并不在意从库的延迟,延迟多少都一样计算(有同事对此不理解,可以参考我的前一篇文章),不会影响计算结果的正确性(但是我们还是会检测延迟,因为延迟太多会影响业务,所以总是要加上—max-lag来限流)。
pt-table-sync则不同。它首先要完成chunk的checksum值的计算,一旦发现主从上同样的chunk的checksum值不同,就深入到该chunk内部,逐行比较并修复有问题的行。其计算逻辑描述如下(以修复主从结构的数据不一致为例,业务双写的情况修复起来更复杂—因为涉及到冲突解决和基准选择的问题,限于篇幅,这里不介绍):
1. 对每一个从库,每一个表,循环进行如下校验和修复过程。
2. 对每一个chunk,在校验时加上for update锁。一旦获得锁,就记录下当前主库的show master status值。
3. 在从库上执行select master_pos_wait()函数,等待从库sql线程执行到show master status得到的位置。以此保证,主从上关于这个chunk的内容均不再改变。
4. 对这个chunk执行checksum,然后与主库的checksum进行比较。
5. 如果checksum相同,说明主从数据一致,就继续下一个chunk。
6. 如果checksum不同,说明该chunk有不一致。深入chunk内部,逐行计算checksum并比较(单行的checksum的比较过程与chunk的比较过程一样,单行实际是chunk的size为1的特例)。
7. 如果发现某行不一致,则标记下来。继续检测剩余行,直到这个chunk结束。
8. 对找到的主从不一致的行,采用replace into语句,在主库执行一遍以生成该行全量的binlog,并同步到从库,这会以主库数据为基准来修复从库;对于主库有的行而从库没有的行,采用replace在主库上插入(必须不能是insert);对于从库有而主库没有的行,通过在主库执行delete来删除(pt-table-sync强烈建议所有的数据修复都只在主库进行,而不建议直接修改从库数据;但是也有特例,后面会讲到)。
9. 直到修复该chunk所有不一致的行。继续检查和修复下一个chunk。
10. 直到这个从库上所有的表修复结束。开始修复下一个从库。
重要选项
安全选项
—[no]check-triggers 检查是否有触发器,有则警告
—[no]foreign-key-checks 默认检查主外键约束,有则警告
—[no]unique-checks 检查是否有唯一索引,无则警告
过滤选项
—ignore-databases
—ignore-engines
—ignore-tables
其他选项
—replicate=s 与pt-table-checksum结合起来,只修复,而不校验。使用pt-table-checksum之前校验的结果
—bidirectional 双向同步。通常都以主库的数据为准,如果开启双向同步,就要定义冲突解决规则,会比较复杂
pt-table-checksum命令
cd /data/work/percona-toolkit-2.1.1/bin
./pt-table-sync --print h='192.168.0.90',u='superdba',p='*****',P=3650,D='expert',t='doctor' --sync-to-master h=192.168.0.5,P=3650
由于对表需要权限过大 故用superdba
前面是slave ip,port,user,password
后面是master ip,port,user,password
D–database
t-table
--print :打印,但不执行命令。
--execute :执行命令。
此时表明已经修复完成。可以重新再检测一遍,确认是否修复;
replace 表必须有主键或者唯一索引,并且此表不能存在触发器, 否则此方案不适用