1. 程式人生 > >pt-table-checksum配置詳解

pt-table-checksum配置詳解

pt-table-checksum

在主庫執行:
mysql>GRANT SELECT, PROCESS, SUPER, REPLICATION SLAVE,CREATE,DELETE,INSERT,UPDATE ON . TO ‘USER‘@‘MASTER_HOST‘ identified by ‘PASSWORD‘;
註:創建用戶,這些權限都是必須的,否則後續執行時會報錯,當然,如果不想授予這麽多權限,那就需要把權限對應的活先自己幹了或者直接在命令行指定,比如如果不想設create權限的話,需要自己指定庫和表(具體參看下面的參數介紹:--replicate)
shell> ./pt-table-checksum --host=‘master_host‘ --user=‘user‘ --password=‘password‘ --port=‘port‘ --databases=databases --tables=tables --recursion-method=processlist
註: (1)在有些情況下,recursion-method如果不設會報錯:Diffs cannot be detected because no slaves were found. 其參數有四:processlist/hosts/dsn=DSN/no,用來決定查找slave的方式是show full processlist還是show slave hosts還是命令行直接指定還是壓根就不準備找從庫,具體見下面參數介紹
(2)主從的端口必須一致,如果不一致就需要用DSN方法進行指定,否則會報找不到從庫的錯誤,如果能連到從庫服務器但沒有指定端口,默認會尋找3306端口
(3)被檢查的主從binlog_format必須為statement,如果不是statement-based,那就添加參數--no-check-binlog-format來避開binlog格式檢查
(4)檢查結果會輸出到默認建立的percona庫中的checksums表中,並會輸出統計信息到屏幕,diffs列展示主從數據不一致的塊的數目,如果都是0,恭喜,數據是一致的

一. 運行原理

pt-table-checksum運行在主庫上,通過show processlist或show slave hosts或DSN方式來確定從庫並連接,默認使用crc32算法來進行數據校驗,該工具之所以需要把binlog設置為statement格式,是因為該工具能得出主從是否一致所依賴的就是statement基礎上同樣的SQL語句在主從庫上各自的執行結果,主庫進行檢查後sql語句傳給從庫,從庫執行一遍後,也得到自己的結果,執行語句是:

SELECT COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS(‘#‘, 各種列名)) AS UNSIGNED)), 10, 16)), 0) AS crc FROM database.table FORCE INDEX(PRIMARY) WHERE ((id >= ‘1‘)) AND ((id <= ‘1000‘))

註: where的條件是根據系統繁忙程度計算出的要執行的範圍
cnt是目前檢查的塊包括的行數,unsigned是計算出的該塊數據的校驗值

如果主庫和從庫得出的這兩個值都是一樣的,那數據就是一致的,如果不一樣,那就主從不一致,當然,字符集、浮點數之類的問題需要提前規避,以免錯判

工具將主從各自得到的結果處理後放到checksums表中並呈現一些結果在屏幕輸出中,work over

二. 安全性保障

pt-table-checksum采用了很多措施來保證檢查過程中的安全性,默認參數是可以保障使用安全的,不過參數可以配置,所以需要詳細了解參數的功能後再進行更改,否則最好采用默認

先了解一下工具在執行過程中做了些什麽:

主庫

SET SESSION innodb_lock_wait_timeout=1 /只針對innodb表/
SET SESSION wait_timeout=10000
SET SQL_MODE=‘NO_AUTO_VALUE_ON_ZERO,NO_ENGINE_SUBSTITUTION‘
SET @@binlog_format = ‘STATEMENT‘
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
SET @@SQL_QUOTE_SHOW_CREATE = 1 /保證檢查安全的相關設置/

CREATE DATABASE IF NOT EXISTS percona
CREATE TABLE IF NOT EXISTS percona.checksums /創建校驗值存放的庫和表/

SHOW GLOBAL STATUS LIKE ‘Threads_running‘ /檢查系統運行情況/

SHOW DATABASES
SHOW TABLES FROM database
USE database
SHOW CREATE TABLE database.a
EXPLAIN SELECT FROM database.a WHERE 1=1
SELECT /
!40001 SQL_NO_CACHE / id FROM database.a FORCE INDEX(PRIMARY) ORDER BY id LIMIT 1 /first lower boundary/
SELECT /
!40001 SQL_NO_CACHE / id FROM database.a FORCE INDEX (PRIMARY) WHERE id IS NOT NULL ORDER BY id LIMIT 1 /key_len/
EXPLAIN SELECT /
!40001 SQL_NO_CACHE / FROM database.a FORCE INDEX (PRIMARY) WHERE id >= ‘1‘ /key_len/

/每次用use database來確定數據庫並依次只選擇一個表進行詳細數據量分析/

USE percona
DELETE FROM percona.checksums WHERE db = ‘database‘ AND tbl = ‘a‘

/避免之前有過檢查並保存有該表的檢查信息,將對應信息刪掉/

USE database
EXPLAIN SELECT /!40001 SQL_NO_CACHE / id FROM database.a FORCE INDEX(PRIMARY) WHERE ((id >= ‘1‘)) ORDER BY id LIMIT 999, 2 /next chunk boundary/
SELECT /!40001 SQL_NO_CACHE / id FROM database.a FORCE INDEX(PRIMARY) WHERE ((id >= ‘1‘)) ORDER BY id LIMIT 999, 2 /next chunk boundary/

/每次檢查表時,第一個塊的行數固定為1000,之後會根據系統繁忙程度計算出在規定時間內能處理的行數來確定為一個chunk,默認時間為0.5秒,可以更改/

EXPLAIN SELECT COUNT() AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS(‘#‘, id, name, type)) AS UNSIGNED)), 10, 16)), 0) AS crc
FROM database.a FORCE INDEX(PRIMARY) WHERE ((id >= ‘1‘)) AND ((id <= ‘1000‘)) /
explain checksum chunk/
REPLACE INTO percona.checksums (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT ‘database‘, ‘a‘, ‘1‘, ‘
PRIMARY‘, ‘1‘, ‘1000‘, COUNT(
) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS(‘#‘, id, name, type)) AS UNSIGNED)), 10, 16)), 0) AS crc FROM database.a FORCE INDEX(PRIMARY) WHERE ((id >= ‘1‘)) AND ((id <= ‘1000‘)) /checksum chunk/

/explain下確定下執行計劃,然後開始真正的checksum工作,是用 REPLACE..SELECT語句計算數據情況並將結果插入到checksums表中/

SHOW WARNINGS
UPDATE percona.checksums SET chunk_time = ‘0.003725‘, master_crc = ‘a9bd6d97‘, master_cnt = ‘1000‘ WHERE db = ‘database‘ AND tbl = ‘a‘ AND chunk=‘1‘

/檢查是否有警告,進一步完善checksums表中的檢查信息/

一個塊的檢查結束,開始下一個塊或下一個表

從庫

跟主庫類似,少了一些設置及explain過程,但多了一個show slave status的檢查,來輔助工具判斷從庫連接和延遲等情況,來確定檢查是否繼續,暫停還是退出

所有檢查執行完後會有這樣一個語句來報出檢查結果

SELECT CONCAT(db, ‘.‘, tbl) AS table, chunk, chunk_index, lower_boundary, upper_boundary, COALESCE(this_cnt-master_cnt, 0) AS cnt_diff, COALESCE(this_crc <> master_crc OR ISNULL(master_crc) <> ISNULL(this_crc), 0) AS crc_diff, this_cnt, master_cnt, this_crc, master_crc FROM percona.checksums WHERE (master_cnt <> this_cnt OR master_crc <> this_crc OR ISNULL(master_crc) <> ISNULL(this_crc)) AND (db=‘database‘ AND tbl=‘a‘)

pt-table-checksum一次只針對一個表,而且會根據表的大小以及當前系統的繁忙程度,計算出一次檢查中能包含的數據行數,來盡量避免對線上服務的影響,如果在執行過程中遇到突發的負載增加,還會自動的將檢查停下來等待,所以即使面對成千上萬的數據庫和表時,它也能順利的進行檢查

在檢查過程中,工具會隨時對主從連接情況進行檢查,如果從庫延遲太大,主從復制中斷,檢查會停下來等待;這裏需要註意的是主從復制過濾,因為這種情形下,主從數據庫中的庫表存在情況不一致,檢查過程中的執行語句會與當前的主從復制過程沖突導致主從復制進程失敗,所以如果有過濾存在,需要指定參數--no-check-replication-filters

在一個塊的數據被檢查之前,會先執行explain操作,來確定執行該檢查的安全性,如果太大不能在指定時間內完成檢查的話就會將該塊數據跳過,另外,如果主庫上整表的數據特別少或幹脆是空表,並不會直接將整表當做一個塊去檢查,而是會再去從庫,確定從庫中也是有同樣少的數據,避免從庫表數據太多卻被當成一個塊執行造成的從庫數據阻塞

另外還有一些安全保護設置,在上面的執行流程中已經列出來了,如設置innodb_lock_wait_timeout=1,如果鎖等待超過1S,就放棄此次執行

在執行過程中如果遇到任何異常,可隨時中斷進程,如kill或CTRL-C,不會造成任何影響,後面想從此次中斷繼續檢查時,簡單的采用--resume就可以

三. 參數介紹

  1. 連接主從庫的參數:

--host --socket --user --password --pid --port

  1. 確定比較範圍的參數

(1) 指定庫

--databases / --ignore-databases 要比較的庫 / 比較過程中忽略這些庫

--databases-regex / --ignore-databases-regex 同上,不過可以用正則匹配

(2) 指定表

--tables / --ignore-tables 要比較的表 / 比較過程中忽略這些表

--tables-regex / --ignore-tables-regex 同上,不過可以用正則匹配

(3) 指定列

--columns / --ignore-columns 要比較的列 / 比較過程中忽略這些列

(4) 直接指定表範圍

--where 直接指定表中要比較的範圍

(5) 根據引擎選表

--engines / --ignore-engines 比較指定的引擎表 / 比較過程中忽略含有這些引擎的表

  1. 指定連接中斷後行為的參數

--resume 如果主從一致性檢查中途中斷的話,可以用這個參數來使工具從上次中斷時檢查的最後一個表開始繼續檢查

--retries 如果在檢查過程中有非致命性的中斷的話,如被kill或者從庫延遲等,指定該參數後,工具會自動嘗試重連

  1. 需重點關註的參數

(1) --[no]check-binlog-format

  默認會檢查binlog-format,如果不是statment,就會報錯退出,想避免該檢查可以設置--no-check-binlog-format

(2) --recursion-method

參數有四:processlist/hosts/dsn=DSN/no,默認是processlist,hosts,但最好還是指定一下,建議指定--recursion-method=processlist,no一般不使用

dsn=DSN方法使用時,需要先去庫裏創建一個表,比如在percona庫中建一個dnsn表

建表語句是: 

CREATE TABLE dsns (id int(11) NOT NULL AUTO_INCREMENT,parent_id int(11) DEFAULT NULL,dsn varchar(255) NOT NULL,PRIMARY KEY (id));
建好後插入主從復制信息數據,如:insert into table dsns(dsn) values(h=slave_host,u=repl_user,p=repl_password,P=port );

然後就可以使用DSN方法了:命令為:--recursion-method dsn=D=percona,t=dsns.

(3) --replicate

用來指定存放計算結果的表名, 默認是percona.checksums,工具會默認自動創建庫percona和表checksums並將checksum的檢查結果輸入到這個表中,如果自己用該參數去指定表的話,表結構必須是:

復制代碼
CREATE TABLE checksums (
db char(64) NOT NULL,
tbl char(64) NOT NULL,
chunk int NOT NULL,
chunk_time float NULL,
chunk_index varchar(200) NULL,
lower_boundary text NULL,
upper_boundary text NULL,
this_crc char(40) NOT NULL,
this_cnt int NOT NULL,
master_crc char(40) NULL,
master_cnt int NULL,
ts timestamp NOT NULL,
PRIMARY KEY (db, tbl, chunk),
INDEX ts_db_tbl (ts, db, tbl)
) ENGINE=InnoDB;
復制代碼
需要註意的是存儲引擎設置,如果檢查的表是innodb表,就設置innodb引擎,如果檢查的表和checksums表的引擎不一致,如分別是myisam和innodb,會引起復制錯誤:“different error on master and slave.”!!!

  1. 其他部分參數詳述:

(1) --[no]check-replication-filters

 默認在檢查到在主從復制過程中有被用..ignore..過濾掉的表,檢查會中斷並退出,如果想避開這個檢查可以設置--no-check-replication-filters

(2) --chunk-index(type: string)

 工具默認在分塊時會選取最合適的索引來explain確定chunk的大小,但如果你希望用其他索引來執行,可以用該參數來指定,工具會以FORCE INDEX的形式把指定的索引加進去

(3) --chunk-index-columns(type: int)

 可以用來指定組合索引中使用前幾個列來輔助分塊

(4) --chunk-size

 直接確定chunk的大小,默認1000行數據,但不建議使用,建議使用--chunk-time代替

(5) --chunk-time

 默認是0.5秒,工具會根據當前系統運行繁忙程度計算出在該指定時間內可以處理的數據行數(即chunk),比較靈活

(6) --[no]empty-replicate-table

 默認yes,每次檢查表之前都去把checksums表中已有的該表信息刪掉,以利於後續重新插入新檢查信息

(7) --float-precision(type: int)

 設置浮點數的四舍五入方式,以避免不同版本間或其他特定情況中,主從間因浮點數四舍五入的方式不同而導致查出不一致,If you specify a value of 2, for example, then the values 1.008 and 1.009 will be rounded to 1.01, and will checksum as equal

(8) --function

 計算checksum值時的函數,默認是CRC32,其他還有FNV1A_64, MURMUR_HASH, SHA1, MD5等

(9) --max-lag

默認1S,主從最大延遲,超過這個延遲時間,就會停下來等待從庫同步,確定方法是采用Seconds_Behind_Master的值

(10) --progress

指定後可以按設定的參數將執行過程中的運行情況輸出到STDERR,如主從延遲時從庫的等待,等待時間等,指定時後跟兩個參數值,默認是 "time,30",前一個參數有:percentage, time, or iterations;後一個指定百分比,具體時間或者間隔的數目

四. 結果分析

        TS ERRORS  DIFFS  ROWS  CHUNKS SKIPPED    TIME TABLE

10-20T08:36:50 0 0 200 1 0 0.005 db1.tbl1
10-20T08:36:50 0 0 603 7 0 0.035 db1.tbl2
10-20T08:36:50 0 0 16 1 0 0.003 db2.tbl3
10-20T08:36:50 0 0 600 6 0 0.024 db2.tbl4

復制代碼
TS
The timestamp (without the year) when the tool finished checksumming the table.
ERRORS
The number of errors and warnings that occurred while checksumming the table. Errors and warnings are printed to standard error while the table is in progress.
DIFFS
The number of chunks that differ from the master on one or more replicas. If --no-replicate-check is specified, this column will always have zeros. If --replicate-check-only is specified, then only tables with differences are printed.
ROWS
The number of rows selected and checksummed from the table. It might be different from the number of rows in the table if you use the –where option.
CHUNKS
The number of chunks into which the table was divided.
SKIPPED
The number of chunks that were skipped due to errors or warnings, or because they were oversized.
TIME
The time elapsed while checksumming the table.
TABLE
The database and table that was checksummed.
復制代碼

pt-table-checksum配置詳解