環(huán)境及關(guān)鍵配置:oracle mysql 5.6.31拗引、pt-table-checksum 3.0.4
binlog_format : row
現(xiàn)象:通過(guò)工具進(jìn)行master slave 數(shù)據(jù)表的比對(duì),命令如下:
無(wú)法檢查出主從庫(kù)里表一致的情況碱工。
pt-table-checksum \
--host=172.17.0.2 \
--port=3306 \
--user=root \
--password=root \
--tables=test.sbtest1 \
--nocheck-replication-filters \
--nocreate-replicate-table \
--nocheck-binlog-format \
--replicate=percona.checksums \
--recursion-method dsn=t=percona.dsns
原因:簡(jiǎn)單說(shuō)明下工具的原理
工具會(huì)在主庫(kù)上建立表checksum注益,表中有字段this_crc,this_cnt,master_crc,master_cnt四個(gè)字段杉辙。
主庫(kù)建表會(huì)同步到從庫(kù)鼓寺,this是從庫(kù)表的一個(gè)chunk的值,master是主庫(kù)相同chunk的值法梯,對(duì)這四個(gè)字段進(jìn)行比對(duì)苔货,如果相等犀概,則數(shù)據(jù)一致。
那么兩組數(shù)據(jù)夜惭,四個(gè)值如何得到姻灶。
pt-table-checksum會(huì)先修改binlog_format=statement,再執(zhí)行兩次修改诈茧,第一次replace的方式修改this_crc,this_cnt产喉,以“變量”值在主庫(kù)執(zhí)行:
REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT 'test', 't1', '1', NULL, NULL, NULL, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `t`, CONCAT(ISNULL(`t`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `test`.`t1` /*checksum table*/
語(yǔ)句復(fù)制到從庫(kù)執(zhí)行,如果主從的同一個(gè)chunk不一致敢会,則寫(xiě)入到值this_crc曾沈,this_cnt也會(huì)不一致
第二次update的方式修改master_crc,master_cnt
則是以master的值作為“常量”進(jìn)行更新,例如:
UPDATE `percona`.`checksums` SET chunk_time = '0.005717', master_crc = '435a7b4f', master_cnt = '3' WHERE db = 'test' AND tbl = 't1' AND chunk = '1'
則從庫(kù)會(huì)復(fù)制到主庫(kù)的值鸥昏,然后四個(gè)值兩兩比對(duì)塞俱,得到一致或者不一致。
那么為什么會(huì)出現(xiàn)無(wú)法檢查出不一致的情況呢吏垮。
因?yàn)槟_本沒(méi)有執(zhí)行set binlog_format=statement
試想下障涯,如果沒(méi)有修改復(fù)制模式,而主庫(kù)的復(fù)制模式是row或者mixed膳汪,則第一次的replace會(huì)使用row的方式進(jìn)行復(fù)制唯蝶,那么從庫(kù)表里的this和master兩組字段數(shù)據(jù)始終會(huì)保持一致。
比對(duì)pt-table-checksum工具3.0.3和3.0.4版本旅敷,發(fā)現(xiàn)問(wèn)題出在:
去掉這個(gè)if判斷修改此bug
附:
pt-table-checksum關(guān)鍵過(guò)程
引用自:http://keithlan.github.io/2016/05/25/pt_table_checksum/
master> /!50108 SET @@binlog_format := ‘STATEMENT’/ 設(shè)置binlog-format為statement
master> SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ 這是隔離級(jí)別為RR生棍,利用RR的特性讓數(shù)據(jù)在這一刻靜止颤霎,就不用加鎖了媳谁。
master> checksums表:REPLACE INTO select設(shè)置this_cnt, this_crc(傳遞到slave,這其實(shí)設(shè)置slave每個(gè)chunk的cnt,crc)友酱,算法來(lái)自:COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(主鍵) AS UNSIGNED)), 10, 16)), 0)
slave> 當(dāng)同步追上后晴音,開(kāi)始執(zhí)行REPLACE INTO select,然后設(shè)置slave每個(gè)chunk的cnt,crc
master> checksums表:update master_cnt,master_crc 缔杉,這是設(shè)置master每個(gè)chunk的cnt锤躁,crc
slave> 當(dāng)同步追上后,開(kāi)始執(zhí)行update master_cnt,master_crc 或详,這是設(shè)置master每個(gè)chunk的cnt系羞,crc
以上,基本完成霸琴。 接下來(lái)只需要去checksums表中找 master_cnt <> this_cnt or OR master_crc <> this_crc 的記錄就行椒振。
在做查詢校驗(yàn)時(shí),select語(yǔ)句有兩個(gè)小技巧:
/*!40001 SQL_NO_CACHE */??? 不加載數(shù)據(jù)到innodb buffer里梧乘,避免大量的內(nèi)存被換出
FORCE INDEX 強(qiáng)制使用同樣的索引