pt-table-checksum/pt-table-sync的工作原理


pt-tables-checksum原理:


1.set @@binlog_format = statement ,这是一个session级别的设置,并不会影响整个binlog的格式

2.检查表是否有唯一键

3.查找chunk的最大唯一键id和最小唯一键id

4.查询这些数据,并将这些数据通过concat_ws,转化成一个字符串然后通过crc32核对检验码

生成replace  into  table_name  select  ********************

5.生成update 语句


具体语句如下:

REPLACE INTO `mysql`.`cksum` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) 

SELECT 'agent', 'iw_agent_port_record_2015', '432', 'PRIMARY', '4659216', '4669215', COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `id`, `agent_id`, `group_id`, `mendian_id`, `area_id`, `big_area_id`, `city_id`, `duoshenqu_id`, `mobile`, `name`, `mendian_name`, `port_num`, `new_num`, `online_num`, `usable_online_total_num`, `fresh_num`, `usable_fresh_total_num`, `click_num`, `record_date`, `biz_type`, `create_time`, `add_customer`, `port_input_fresh`, `port_input_recharge`, `better_house`, `can_add_house`, `port_count`, UNIX_TIMESTAMP(`updatetime`), `data_input_flag`, `repeat_customer`, `agent_add_customer`, `paid_performance`, `outstanding_performance`, `repeat_customer_person`, `agent_add_customer_person`, CONCAT(ISNULL(`agent_id`), ISNULL(`group_id`), ISNULL(`mendian_id`), ISNULL(`area_id`), ISNULL(`big_area_id`), ISNULL(`city_id`), ISNULL(`duoshenqu_id`), ISNULL(`mobile`), ISNULL(`mendian_name`), ISNULL(`port_num`), ISNULL(`new_num`), ISNULL(`online_num`), ISNULL(`usable_online_total_num`), ISNULL(`fresh_num`), ISNULL(`usable_fresh_total_num`), ISNULL(`click_num`), ISNULL(`create_time`), ISNULL(`add_customer`), ISNULL(`port_input_fresh`), ISNULL(`port_input_recharge`), ISNULL(`better_house`), ISNULL(`can_add_house`), ISNULL(`port_count`), ISNULL(`updatetime`), ISNULL(`data_input_flag`), ISNULL(`repeat_customer`), ISNULL(`agent_add_customer`), ISNULL(`paid_performance`), ISNULL(`outstanding_performance`), ISNULL(`repeat_customer_person`), ISNULL(`agent_add_customer_person`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `agent`.`iw_agent_port_record_2015` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= '4659216')) AND ((`id` <= '4669215')) /*checksum chunk*/


UPDATE `mysql`.`cksum` SET chunk_time = '0.093958', master_crc = 'd9dd0b15', master_cnt = '10000' WHERE db = 'agent' AND tbl = 'iw_agent_port_record_2015' AND chunk = '432


这些语句按照一定顺序在slave上执行,就可以得到slave上chunk 数据的crc32校验码了。


存在bug

这个bug可以理解为,表中列的数据类型不能全部为数据类型。

http://blog.chinaunix.net/uid-16844903-id-3480621.html



pt-table-sync的工作原理:

这个工具可以单独使用,也可以是基于pt-table-checksum的检验结果使用


基于pt-table-checksum结果集的pt-table-sync的工作原理

1.找到数据不一致的chunk

1.开启事务 for update 锁定一条记录

2.生成crc32校验码 

3.在主库上执行 show master status 得到 binlog  postion  

4.在从库上 select master_pos_wait(binlog_file,postion)

5.等到从库执行到 binlog postion 在从库上 生成crc32校验码, 

6.比对两个crc32 检验码 是否一样 ,一样 就 进行下一条数据的校验, 

如果不一样,生成语句(replace[inset,update],delete)

7.提交事务



pt-table-sync的工作原理

1.检查表是否有唯一键

2.查找chunk的最大id和最小id

3.开启事务 对chunk加for update,

4.通过concat_ws,crc32算出校验码

5.在从库上执行select master_pos_wait(binlogfile,postion)

6.然后等待从库执行到 binlogfile ,postion 位置, 生成chunk的crc32检验码

7.比对两个crc32校验码,如果crc32校验码一样,就进行下一个chunk的校验,

如果crc32校验码不一样,就深入到chunk的内部比对行的crc32检验码

8.提交事务




以下是一个简易的校验脚本


#!/usr/bin/env sh

PATH="/usr/local/bin:/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/bin"


m_host='db-servername'

m_user='root'

m_pwd='asdf'

chunksize=10000

m_db='information_schema,mysql,performance_schema,test'


cd /tmp/20160721


pt-table-checksum --nocheck-replication-filters --no-check-binlog-format     --replicate=mysql.cksum  --recursion-method=hosts   --ignore-databases=${m_db}     h=${m_host}

,u=${m_user},p=${m_pwd}  --chunk-size=${chunksize}  



# 从主库开始检验,校验所有的服务器

# pt-table-sync --replicate=mysql.cksum --charset=utf8 h=db-master,u=root,p='111111',P=3306 --print


# 从 slave开始检验 只校验制定的服务器

# pt-table-sync --print --replicate mysql.cksum --sync-to-master h=db-report,P=3307,u='root',p='11111'



推荐阅读:

http://www.linuxidc.com/Linux/2014-11/109852.htm