pt-table-checksum解讀【轉】

pt-table-checksum是目前能夠說是最好的查看主從一致性的工具html

先來個使用例子,有助快速上手使用mysql

在主庫執行: 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語句傳給從庫,從庫執行一遍後,也獲得本身的結果,執行語句是: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是計算出的該塊數據的校驗值shell

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

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

 

二. 安全性保障服務器

pt-table-checksum採用了不少措施來保證檢查過程當中的安全性,默認參數是能夠保障使用安全的,不過參數能夠配置,因此須要詳細瞭解參數的功能後再進行更改,不然最好採用默認
socket

先了解一下工具在執行過程當中作了些什麼:ide


 主庫


 

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

 

2.  肯定比較範圍的參數

(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                           比較指定的引擎表   /   比較過程當中忽略含有這些引擎的表

 

3.  指定鏈接中斷後行爲的參數

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

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

 

4.  需重點關注的參數

(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.」!!!

 

5. 其餘部分參數詳述:

(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解讀 - 王小樣 - 博客園 https://www.cnblogs.com/xiaoyanger/p/5584554.html

相關文章
相關標籤/搜索