percona-toolkit 之 【pt-table-checksum】、【pt-table-sync】說明


摘要:

      工作上需要把一個從庫提升為主庫,但對從庫和主庫的數據一致性不能保證一樣,所以就利用 pt-table-checksum 工作來檢查主從的一致性(之前寫過用1.0.1的版本可以進行操作的文章,但是在新版本操作就不行了,只能重新來過)以及通過 pt-table-sync 如何修復這些不一致的數據。

前提:

下載地址:wget www.percona.com/downloads/percona-toolkit/2.2.2/percona-toolkit-2.2.2.tar.gz

安裝方法:perl Makefile.PL;make;make install

使用方法:

pt-table-checksum [OPTIONS] [DSN]

pt-table-checksum在主<M>上通過執行校驗的查詢對復制的一致性進行檢查,對比主從的校驗值,從而產生結果。DSN指向的是主的地址,該工具的退出狀態不為零,如果發現有任何差別,或者如果出現任何警告或錯誤,更多信息請見官網。
不制定任何參數,會直接對本地的所有數據庫的表進行檢查。

pt-table-checksum -S /var/run/mysqld/mysqld.sock

現在開始使用它,檢查主從狀態:
表信息:

View Code
主庫:
root@localhost : rep_test 04:17:29>select * from test1;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
|  4 | d    |
+----+------+
4 rows in set (0.00 sec)

從庫:
dba@192.168.200.201 : rep_test 04:17:25>select * from test1;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
|  4 | d    |
+----+------+
3 rows in set (0.00 sec)

執行:

zhoujy@zhoujy:~$ pt-table-checksum  --nocheck-replication-filters --replicate=rep_test.checksums --databases=rep_test --tables=test1 h=127.0.0.1,u=root,p=123456,P=3306 TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE 05-08T16:21:06      0      1        4       1       0   0.012 rep_test.test1
TS            :完成檢查的時間。
ERRORS        :檢查時候發生錯誤和警告的數量。
DIFFS         :0表示一致,1表示不一致。當指定--no-replicate-check時,會一直為0,當指定--replicate-check-only會顯示不同的信息。
ROWS          :表的行數。
CHUNKS        :被划分到表中的塊的數目。
SKIPPED       :由於錯誤或警告或過大,則跳過塊的數目。
TIME          :執行的時間。
TABLE         :被檢查的表名。

參數的意義:

--nocheck-replication-filters :不檢查復制過濾器,建議啟用。后面可以用--databases來指定需要檢查的數據庫。
--no-check-binlog-format : 不檢查復制的binlog模式,要是binlog模式是ROW,則會報錯。
--replicate-check-only :只顯示不同步的信息。 --replicate= :把checksum的信息寫入到指定表中,建議直接寫到被檢查的數據庫當中。 --databases= :指定需要被檢查的數據庫,多個則用逗號隔開。
--tables= :指定需要被檢查的表,多個用逗號隔開 h=127.0.0.1 :Master的地址 u=root :用戶名 p=123456 :密碼 P=3306 :端口

更多的參數請見官網,上面指出來的是常用的,對該場景夠用的參數。

好了,命令介紹完了,一起解釋下上面執行的效果:
通過DIFFS 是1 就可以看出主從的表數據不一致。怎么不一致呢? 通過指定--replicate=rep_test.checksums 參數,就說明把檢查信息都寫到了checksums表中。
進入SLAVE相應的庫中查看checksums表的信息:

dba@192.168.200.201 : rep_test 05:19:13>select * from checksums\G;
*************************** 1. row ***************************
            db: rep_test
           tbl: test1
         chunk: 1
    chunk_time: 0.000257
   chunk_index: NULL
lower_boundary: NULL
upper_boundary: NULL 
      this_crc: b24c0933   #從的
      this_cnt: 3          #從的 master_crc: f2890e1c   #主的
    master_cnt: 4          #主的
            ts: 2013-05-08 17:18:18
1 row in set (0.00 sec)

通過上面的 this_crc <> master_crc 更能清楚的看出他們的不一致了,通過chunk知道是這個張表的哪個塊上的記錄出現不一致。要是主的binlog模式是Row 則會報錯:

Replica db2 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.

從錯誤信息得出,要是不改binlog模式的話,則執行上面的命令時候要指定:
--no-check-binlog-format,即:

pt-table-checksum  --nocheck-replication-filters --no-check-binlog-format  --replicate=rep_test.checksums --databases=rep_test --tables=test1,test2  h=127.0.0.1,u=root,p=123456,P=3306

注意:

要是在執行命令的過程遇到找不到從服務器的錯誤:

Diffs cannot be detected because no slaves were found.  Please read the --recursion-method documentation for information.

上面的提示信息很清楚,因為找不到從,所以執行失敗。用參數--recursion-method 可以指定模式解決,關於--recursion-method參數的設置有:

METHOD       USES
===========  =============================================
processlist  SHOW PROCESSLIST
hosts        SHOW SLAVE HOSTS
cluster      SHOW STATUS LIKE 'wsrep\_incoming\_addresses'
dsn=DSN      DSNs from a table
none         Do not find slaves

默認是通過show processlist 找到host的值或show slave hosts 找到host的值。那上面為什么會找不到從呢?

個人猜測:測試下來是因為在同一個服務器上開啟了2個實例互為主從,通過processlist 得到的 host 主從一樣,但是沒有,而 show slave hosts,因為從上沒有指定所以也取不到需要的信息。解決辦法:

在從的配置文件里加:

report_host = 192.168.200.25   #設置成本地地址

這樣在主上執行 show slave hosts 就有信息了:

root@localhost : (none) 02:47:43>show slave hosts;
+-----------+----------------+------+----------+------+-------------------+-----------+
| Server_id | Host           | User | Password | Port | Rpl_recovery_rank | Master_id |
+-----------+----------------+------+----------+------+-------------------+-----------+
|         2 | 192.168.200.25 |      |          | 3307 |                 0 |         1 |
+-----------+----------------+------+----------+------+-------------------+-----------+
1 row in set (0.00 sec)

最后再執行以上命令(多加--recursion-method=hosts 參數)

zhoujy@zhoujy:~$ pt-table-checksum --recursion-method=hosts --no-check-binlog-format --nocheck-replication-filters  --replicate=aaa.checksums --databases=aaa --tables=test h=192.168.200.25,u=root,p=123456,P=3306
            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
10-24T14:54:43      0      1        6       1       0   0.306 aaa.test

通過上面找到了這些不一致的數據表,如何同步數據呢?即如何修復MySQL主從不一致的數據,讓他們保持一致性呢?利用另外一個工具 pt-table-sync
使用方法:

pt-table-sync [OPTIONS] DSN [DSN]

pt-table-sync: 高效的同步MySQL表之間的數據,他可以做單向和雙向同步的表數據。他可以同步單個表,也可以同步整個庫。它不同步表結構、索引、或任何其他模式對象。所以在修復一致性之前需要保證他們表存在。

接着上面的復制情況,主和從的test1數據不一致,需要修復,要是有中文的則需要加上:--charset=utf8,防止亂碼。
執行

root@zhoujy:~# pt-table-sync --replicate=rep_test.checksums h=127.0.0.1,u=root,p=123456 h=192.168.200.201,u=root,p=123456 --charset=utf8 --print REPLACE INTO `rep_test`.`test1`(`id`, `name`) VALUES ('3', 'c')  
#先M的IP,再S的IP
/*percona-toolkit src_db:rep_test src_tbl:test1 src_dsn:h=127.0.0.1,p=...,u=root dst_db:rep_test dst_tbl:test1 dst_dsn:h=192.168.200.201,p=...,u=root lock:1 transaction:0 changing_src:rep_test.checksums replicate:rep_test.checksums bidirectional:0 pid:12285 user:root host:zhoujy*/;

參數的意義:

--replicate=  :指定通過pt-table-checksum得到的表,這2個工具差不多都會一直用。
--databases=  : 指定執行同步的數據庫,多個用逗號隔開。
--tables=     :指定執行同步的表,多個用逗號隔開。
--sync-to-master :指定一個DSN,即從的IP,他會通過show processlist或show slave status 去自動的找主。
h=127.0.0.1服務器地址,命令里有2個ip,第一次出現的是M的地址,第2次是Slave的地址。
u=root        :帳號。
p=123456      :密碼。
--print  :打印,但不執行命令。
--execute     :執行命令。
更多的參數請見官網,上面指出來的是常用的,對該場景夠用的參數。

上面的效果和這個一樣:

zhoujy@zhoujy:~$ pt-table-sync --sync-to-master h=192.168.200.201,u=root,p=123456 --databases=rep_test --tables=test1 --charset=utf8 --print
REPLACE INTO `rep_test`.`test1`(`id`, `name`) VALUES ('3', 'c') 
#用一個IP(SLAVE)就可以了。
/*percona-toolkit src_db:rep_test src_tbl:test1 src_dsn:P=3306,h=192.168.200.25,p=...,u=root dst_db:rep_test dst_tbl:test1 dst_dsn:h=192.168.200.201,p=...,u=root lock:1 transaction:1 changing_src:1 replicate:0 bidirectional:0 pid:20122 user:zhoujy host:zhoujy*/;

好了,命令介紹完了,一起解釋下執行的效果:通過(--print)打印出來了修復數據的sql語句,可以手動的去從行執行,讓他們數據保持一致性。那能否直接執行?當然可以,通過(--execute):

root@zhoujy:~# pt-table-sync --replicate=rep_test.checksums --databases=rep_test --tables=test2,test1 h=127.0.0.1,u=root,p=123456 h=192.168.200.201,u=root,p=123456 --execute
root@zhoujy:~# 

直接執行完畢了,查看數據表:

View Code
主:
root@localhost : rep_test 08:58:41>select * from test1;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
|  4 | d    |
+----+------+
4 rows in set (0.00 sec)

從:
root@192.168.200.201 : rep_test 08:58:56>select * from test1;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
|  4 | d    |
+----+------+
4 rows in set (0.00 sec)

OK,數據已經保持一致了。不過建議還是用--print 打印出來的好,這樣就可以知道那些數據有問題,可以人為的干預下。不然直接執行了,出現問題之后更不好處理。總之還是在處理之前做好數據的備份工作。

注意:要是表中沒有唯一索引或則主鍵則會報錯:

Can't make changes on the master because no unique index exists at /usr/local/bin/pt-table-sync line 10591.

另外補充:
要是從庫有的數據,而主庫沒有,那這個數據怎么處理?在原先的基礎上,在從上添加一條5記錄。

root@zhoujy:~# pt-table-sync --replicate=rep_test.checksums --databases=rep_test,test --tables=test2,test1 h=127.0.0.1,u=root,p=123456 h=192.168.200.201,u=root,p=123456 --print
DELETE FROM `rep_test`.`test1` WHERE `id`='5' LIMIT 1 

/*percona-toolkit src_db:rep_test src_tbl:test1 src_dsn:h=127.0.0.1,p=...,u=root dst_db:rep_test dst_tbl:test1 dst_dsn:h=192.168.200.201,p=...,u=root lock:1 transaction:0 changing_src:rep_test.checksums replicate:rep_test.checksums bidirectional:0 pid:12343 user:root host:zhoujy*/;
REPLACE INTO `rep_test`.`test1`(`id`, `name`) VALUES ('3', 'c')

/*percona-toolkit src_db:rep_test src_tbl:test1 src_dsn:h=127.0.0.1,p=...,u=root dst_db:rep_test dst_tbl:test1 dst_dsn:h=192.168.200.201,p=...,u=root lock:1 transaction:0 changing_src:rep_test.checksums replicate:rep_test.checksums bidirectional:0 pid:12343 user:root host:zhoujy*/;

從上面可以看到,直接把從庫的有的數據給刪除了,沒有的數據進行插入。這樣2邊又保持了 一致性。

要是在shell窗口不想顯示的輸入密碼則可以添加:--ask-pass 參數,如:

zhoujy@zhoujy:~$ pt-table-checksum  --nocheck-replication-filters --no-check-binlog-format  --replicate=rep_test.checksums --ask-pass --databases=rep_test --tables=test1,test2  h=127.0.0.1,u=root,P=3306
Enter MySQL password: 
            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
05-09T13:57:04      0      1        4       1       0   0.015 rep_test.test1
05-09T13:57:04      0      1        1       1       0   0.010 rep_test.test2

zhoujy@zhoujy:~$ pt-table-sync --replicate=rep_test.checksums  --ask-pass h=127.0.0.1,u=root h=192.168.200.201,u=root --print
Enter password for 127.0.0.1: 
Enter password for 192.168.200.201: 
DELETE FROM `rep_test`.`test1` WHERE `id`='5' LIMIT 1;
REPLACE INTO `rep_test`.`test1`(`id`, `name`) VALUES ('4', 'd') ;

 總結:
該工具檢查的表,需要檢查連接的帳號需要有很高的權限,在一般權限行需要加
SELECT, PROCESS, SUPER, REPLICATION SLAVE等權限,測試方便我直接給了ALL的權限,pt-table-checksum 和 pt-table-sync 一起互補使用,檢查一定是在同步操作之前,更多的信息請見 這里 這里這里


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM