mysql主從數據一致性校驗及糾錯工具

目錄mysql

一、概述web

二、percona-tooldit工具的安裝sql

三、新建用戶數據庫

四、pt-table-checksum使用服務器

五、pt-table-sync使用架構

六、我的總結運維

一、概述異步

    假如你是一位運維人員,假如你生產環境上部署了mysql系統,再假如你線上的mysql是基於主從複製的架構,那恭喜你,它將可能會帶給你主從數據不一致的"惡運"。工具

    因爲mysql複製架構原生特性,主從服務器上的數據不可能作」同步「複製,因此延時是必然會有的,即便是不那麼繁忙的服務器上,在業務不繁忙的時間裏,從庫能追上主庫的進度,也可能會由於從服務器崩潰、非法關機、程序bug等因素致使在主庫上寫入的數據與從庫上寫入的數據不一致的問題。而當這種狀況發生時,mysql內部是沒有相應的機制來檢測主從數據一致性的,對用戶而言,你是不知道主從數據已經不一致了。性能

    因此須要一種工具來解決這樣的問題,而percona-toolkit工具集中的pt-table-checksum工具就是能在幾乎不影響mysql性能的前提下高效的,能檢測主從數據不一致的工具。當數據不一致真正產生後,percona-tools工具集中也提供了pt-table-sync工具來修復不一致的數據,這樣可免去從新部署從服務器的麻煩。

    然而在真正的生產環境上,這兩個工具仍是有必定的侷限性,準確的說應該是mysql這種異步複製的架構致使了工具在使用上的侷限性,由於從庫會慢於主庫,因此在校驗主庫上的表與校驗從庫上的表時每每數據是不一致的,這個不致是因爲從庫的延遲而致使的,因此這兩個工具最好運用在如下場景:

a)、從服務器提高爲主服務器時,在新的主服務器上線時須要與舊的主服務器進行數據一致性檢查

b)、數據遷移後,應該進行數據一致性檢查

c)、從庫被誤操做致使數據更新後,應該進行一致性檢查

d)、計劃內的數據一致性檢查

    如下的演示是基於http://zhaochj.blog.51cto.com/368705/1635982一文中搭建的主從複製環境。

二、percona-toolkit工具的安裝

先安裝所依賴的包及percona-toolkit:

1
2
[root@master ~] yum -y  install  perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL perl-IO-Socket-SSL
[root@master ~] rpm -ivh percona-toolkit-2.2.13-1.noarch.rpm

三、新建用戶

    建立一個非root權限的用戶來專門進行數據一致檢測等工做,pt-table-checksum與pt-table-sync須要鏈接到從庫中進行相應的數據查看、數據修改等操做,因此在主庫上建立一個這樣的用戶:

1
2
3
4
5
6
7
8
mysql> GRANT  select ,insert,update,delete,create,process,super,replication slave ON *.* TO monitor@ '192.168.0.%'  IDENTIFIED BY  '111111' ;
Query OK, 0 rows affected (0.01 sec)
 
mysql> GRANT  select ,insert,update,delete,create,process,super,replication slave ON *.* TO monitor@ '127.0.0.1'  IDENTIFIED BY  '111111' ;
Query OK, 0 rows affected (0.00 sec)
 
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

用戶新建好後請測試是否能正常接入主庫和備庫(由於這個用戶也須要鏈接主庫,因此建立了上邊兩個用戶)。這個用戶所須要的權限真很多,沒辦法,這是因爲percona-toolkit中那兩個工具的工做原理所須要的權限,若是爲了省事,也可直接給予ALL的權限。

四、pt-table-checksum使用

在mydb1庫中的tb1表做爲測試,在主庫上查看tb1的內容:

1
2
3
4
5
6
7
8
9
10
11
mysql> SELECT * FROM mydb1.tb1;
+----+-------+------+
id  | name  | age  |
+----+-------+------+
|  1 | tom   |   12 |
|  2 | jem   |   23 |
|  3 | jason |   29 |
|  4 | aaa   |   30 |
|  5 | b     |   69 |
+----+-------+------+
5 rows  in  set  (0.01 sec)

在從庫上查看mydb1.tb1的內容:

1
2
3
4
5
6
7
8
9
10
11
mysql>  select  * from mydb1.tb1;
+----+-------+------+
id  | name  | age  |
+----+-------+------+
|  1 | tom   |   12 |
|  2 | jem   |   23 |
|  3 | jason |   29 |
|  4 | aaa   |   30 |
|  5 | b     |   69 |
+----+-------+------+
5 rows  in  set  (0.00 sec)

此時主從的數據都是一致的,用pt-table-checksum工具測試一下看輸出的是什麼結果:

1
2
3
[root@master ~] # pt-table-checksum  --nocheck-replication-filters --replicate=mydb1.checksums --databases=mydb1 h=127.0.0.1,u=monitor,p=111111
Replica slave has binlog_format ROW  which  could cause pt-table-checksum to  break  replication.  Please  read  "Replicas using row-based replication"  in  the LIMITATIONS section of the tool's documentation.  If you understand the risks, specify --no-check-binlog- format  to disable this check.
#報錯了,由於個人mysql環境的二進制日誌是基於行的,即‘binlog_format=ROW’,若是是基於行的複製環境,percona官方是不建議使用pt-table-checksum工具來進行數據的一致性檢查的,但它又提供了一個選項來跳過此檢查。

各經常使用選項意義:

--nocheck-replication-filters:不檢查複製過慮,咱們用--databases來指定須要檢查的數據庫

--replicate:把校驗的信息寫入指定的表中

--no-check-binlog-format:不檢查二進制日誌文件格式

--replicate-check-only:只顯示有不一致數據的信息

--databases:指定校驗的數據庫,多個用逗號隔開

--tables:指定校驗的表,多個用逗號隔開

h:主機,指主服務器IP

u:賬號

p:密碼


加上「--no-check-binlog-format」選項後再來測試一次:

1
2
3
4
5
[root@master ~] # pt-table-checksum  --nocheck-replication-filters --replicate=mydb1.checksums --no-check-binlog-format --databases=mydb1 --h=127.0.0.1,u=monitor,p=111111
             TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
04-21T18:00:59      0      0        5       1       0   0.280 mydb1.tb1
04-21T18:00:59      0      0        2       1       0   0.331 mydb1.tb2
#注意觀察「DIFFS」那一列,若是數據有不一致的這裏不是「0」值。

運行上邊的命令後可能會報「no slaves were found」相似的錯誤,這裏由於沒法鏈接從服務器所致使。當運行上邊的指令後,pt-table-checksum鏈接支主mysql後會採起遞歸的方法去自動查找主的從服務器有哪些,先是運行「show processlist;」,而後是運行「show slave hosts」來查找,若是遇到不能鏈接從服務器的錯誤時,能夠在從服務器的my.cnf加入「report_host=從服務器IP」來主動告訴主服務器它就主的從,並在運行的pt-table-checksum命令中加上「--recursion-method=hosts」選項,這樣在主服務器能夠用「show slave hosts」指令就可查看到從服務器IP地址。


如今咱們人爲的使主從數據不一致,在從服務器上把tb1表中id號爲5的age那一列改成20:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> update mydb1.tb1  set  age=20 where  id =5;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
mysql>  select  * from mydb1.tb1;
+----+-------+------+
id  | name  | age  |
+----+-------+------+
|  1 | tom   |   12 |
|  2 | jem   |   23 |
|  3 | jason |   29 |
|  4 | aaa   |   30 |
|  5 | b     |   20 |
+----+-------+------+
5 rows  in  set  (0.00 sec)

這樣主從數據就不一致了,咱們再主服務器上運行pt-table-checksum工具來測試一下:

1
2
3
4
5
[root@master ~] # pt-table-checksum  --nocheck-replication-filters --replicate=mydb1.checksums --no-check-binlog-format --recursion-method=hosts --databases=mydb1 h=127.0.0.1,u=monitor,p=111111
             TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
04-21T18:27:00      0      1        5       1       0   0.307 mydb1.tb1
04-21T18:27:01      0      0        2       1       0   0.048 mydb1.tb2
#tb1這個表的"DIFFS"的值變爲了「1」。

接下來該pt-table-sync工具上場了。

五、pt-table-sync使用

能夠用「--print」選項來看一下主從上究竟是哪裏不一致了:

1
2
3
4
[root@master ~] # pt-table-sync --replicate=mydb1.checksums h=127.0.0.1,u=monitor,p=111111 h=192.168.0.202,u=monitor,p=111111 --charset=utf8 --print
REPLACE INTO `mydb1`.`tb1`(` id `, `name`, `age`) VALUES ( '5' 'b' '69' ) /*percona-toolkit src_db:mydb1 src_tbl:tb1 src_dsn:A=utf8,h=127.0.0.1,p=...,u=monitor dst_db:mydb1 dst_tbl:tb1 dst_dsn:A=utf8,h=192.168.0.202,p=...,u=monitor lock:1 transaction:1 changing_src:mydb1.checksums replicate:mydb1.checksums bidirectional:0 pid:3205 user:root host:master*/;
#上邊的輸出信息表示從庫上id=5那行的age的值應該是69。
#命令中有兩組「h=  ,u=   ,p=   」,第一組指定的是主服務器,第二組指向從服務器。

各個經常使用選項的意義:

--replicate=  :表示基於pt-table-checksum工具生成的checksums表來修復有問題的數據

--databases=:表示執行同步的數據庫,多個用逗號隔開

--tables=:    表示執行同步的數據表,多個用逗號隔開

h=   :服務器主機名

u=   :賬號

p=   :密碼

--print:只打印,但不執行命令

--execute:執行命令


確認數據真不一致後那就把「--print」選項換成「--execute」來執行替換語句:

1
[root@master ~] # pt-table-sync --replicate=mydb1.checksums h=127.0.0.1,u=monitor,p=111111 h=192.168.0.202,u=monitor,p=111111 --charset=utf8 --execute

從庫上的數據手動糾正後再運行pt-table-checksum工具來看一下這兩個表的數據是否已經一致了:

1
2
3
4
[root@master ~] # pt-table-checksum --replicate=mydb1.checksums --nocheck-replication-filters --no-check-binlog-format --databases=mydb1 h=127.0.0.1,u=monitor,p=111111
             TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
04-21T21:42:31      0      0        5       1       0   0.309 mydb1.tb1
04-21T21:42:32      0      0        2       1       0   0.304 mydb1.tb2

這樣數據就被成功糾正。

六、我的總結

    這兩個工具通常都是結合起來使用,彌補了mysql沒有數據一致性校驗的機制,讓運維人員在主從複製架構中更能維護得更好。基於percona官方的說明在pt-table-checksum工具中最好讓複製是基於語句的複製,而基於語句和基於行的複製各有各的優缺點,若是考慮到在後期的維護中會經常使用到pt-table-checksum工具,我的認爲仍是該把binlog_format設置爲statement,或者mixed。

最後要說的是,若是在生產環境上真的產生了主備數據不一致,而不是延遲致使的,那在利用這些工具對數據操做時切記記得對源數據要進行備份,無論源數據是無缺的,仍是有些數據已被損壞,你在作數據修復工做前必定要把源數據作一個備份,在數據恢復這樣一個高壓的環境,誰能保證你作的操做都是規範且正確的?若是操做失誤,你起碼還有回滾的機會。

相關文章
相關標籤/搜索