2016-11-27 回答
利用pt-table-checksum工具
它通过在主库执行基于statement的sql语句来生成主库数据块的checksum,把相同的sql语句传递到从库,并在从库上计算相同数据块的checksum,最后,比较主从库上相同数据块的checksum值,由此判断主从数据是否一致。
简单说一下checksum的计算原理
1. 单行数据checksum值的计算
pt工具先检查表的结构,并获取每一列的数据类型,把所有数据类型都转化为字符串,然后用concat_ws()函数进行连接,由此计算出该行的checksum值。checksum默认采用crc32,你可以自己定义效率更高的udf。
2. 数据块checksum值的计算
如果一行一行的计算checksum再去和从库比较,那么效率会非常低下。pt工具选择智能分析表上的索引,然后把表的数据split成一个个chunk,计算的时候也是以chunk为单位。因此引入了聚合函数bit_xor()。它的功能可以理解为把这个chunk内的所有行的数据拼接起来,再计算crc32的值,就得到这个chunk的checksum值。sql语句如下:
这其中还有count(*),用来计算chunk包含的行数。每一次对chunk进行checksum后,pt工具都会对耗时进行统计分析,并智能调整下一个chunk的大小,避免chunk太大对线上造成影响,同时也要避免chunk太小而效率低下。
3. 一致性如何保证
当pt工具在计算主库上某chunk的checksum时,主库可能还在更新,同时从库可能延迟使得relay-log中还有与这个chunk数据相关的更新。
如何保证主库与从库计算的是”同一份”数据,就要加for update当前读锁,这保证了主库的某个chunk内部数据的一致性。
否则,1000个人chekcusm同样的1000行数据,可能得到1000个不同的结果,你无法避开mvcc的干扰!
获得for update锁后,pt工具开始计算chunk的checksum值,并把计算结果保存到pt工具自建的结果表中(采用replace into select的方式),然后释放锁。该语句最终会传递到从库并执行相同的计算逻辑。
校验结束后,在每个从库上,执行如下的sql语句即可看到是否有主从不一致发生
select * from percona.checksums
where master_cnt <> this_cnt or master_crc <> this_crc or isnull(master_crc) <> isnull(this_crc) \