MySQL Replication數據不一致

mha文章:http://467754239.blog.51cto.com/4878013/1695175 j_0026.gif


關於如何驗證主從數據的不一致

pt-table-checksum,它可以檢測master和slave上表結構和數據是否一致


如何解決主從數據不一致

pt-table-sync,它可以修復主從數據不一致


這兩款工具都是由Percona公司提供的,Percona在MySQL的日常管理提供了很多類似的工具。


適用場景

pt-table-checksum是一個在線驗證主從數據一致性的工具,主要用於以下場景

1. 數據遷移前後,進行數據一致性檢查

2. 當主從複製出現問題,待修改完成後,對主從數據一致性檢查

3. 把從庫當成主庫,進行數據更新,產生了'髒數據'

4. 定期校驗


Percona的文檔地址:https://www.percona.com/doc/percona-toolkit/2.2/index.html


一、環境準備

準備一個主從架構的環境,建議是新配置的主從環境,並驗證主從配置是正常的。

1、地址規劃
192.168.1.    master(主機名和角色)
192.168.1.    slave(主機名和角色)
 
2、驗證主從是否一致
登錄slave主機,查看主從同步狀態
[root@slave ~]# mysql -uroot -p123456 -e 'show slave status\G;' |egrep "(Slave_IO_Running:|Slave_SQL_Running:)"
             Slave_IO_Running: Yes    #表示主從ok
            Slave_SQL_Running: Yes


二、安裝

# yum install perl-DBI perl-CPAN perl-devel perl-Time-HiRes perl-DBD-mysql perl-IO-Socket-SSL perl-TermReadKey -y
# wget https://www.percona.com/downloads/percona-toolkit/2.2.15/RPM/percona-toolkit-2.2.15-1.noarch.rpm
# rpm -ivh percona-toolkit-2.2.15-1.noarch.rpm 
 
查看軟件包提供了哪些可用的工具
# rpm -ql percona-toolkit |grep '/usr/bin'
/usr/bin/pt-align
/usr/bin/pt-archiver
/usr/bin/pt-config-diff
/usr/bin/pt-deadlock-logger
/usr/bin/pt-diskstats
/usr/bin/pt-duplicate-key-checker
/usr/bin/pt-fifo-split
/usr/bin/pt-find
/usr/bin/pt-fingerprint
/usr/bin/pt-fk-error-logger
/usr/bin/pt-heartbeat
/usr/bin/pt-index-usage
/usr/bin/pt-ioprofile
/usr/bin/pt-kill
/usr/bin/pt-mext
/usr/bin/pt-mysql-summary
/usr/bin/pt-online-schema-change
/usr/bin/pt-pmp
/usr/bin/pt-query-digest
/usr/bin/pt-show-grants
/usr/bin/pt-sift
/usr/bin/pt-slave-delay
/usr/bin/pt-slave-find
/usr/bin/pt-slave-restart
/usr/bin/pt-stalk
/usr/bin/pt-summary
/usr/bin/pt-table-checksum
/usr/bin/pt-table-sync
/usr/bin/pt-table-usage
/usr/bin/pt-upgrade
/usr/bin/pt-variable-advisor
/usr/bin/pt-visual-explain


三、介紹pt-table-checksum

用法:

pt-table-checksum

描述:

在主master上通過執行校驗的查詢對複製的一致性進行檢查,對比主從的校驗值,從而產生結果。DSN指向的是主的地址.


不指定任何參數,會直接對本地的所有數據庫的表進行檢查。

[root@master ~]# pt-table-checksum -uroot -p123456 --no-check-binlog-format -S /tmp/mysql.sock 
            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
09-18T17:35:00      0      0        2       1       0   0.012 dbtest.tb
09-18T17:35:00      0      0        0       1       0   0.013 mysql.columns_priv
09-18T17:35:00      0      0        0       1       0   0.012 mysql.db
09-18T17:35:00      0      0        0       1       0   0.014 mysql.event
09-18T17:35:00      0      0        0       1       0   0.015 mysql.func
09-18T17:35:01      0      0       40       1       0   0.290 mysql.help_category
09-18T17:35:01      0      0      608       1       0   0.275 mysql.help_keyword
09-18T17:35:01      0      0     1216       1       0   0.284 mysql.help_relation
09-18T17:35:02      0      0      583       1       0   0.343 mysql.help_topic
09-18T17:35:02      0      0        0       1       0   0.040 mysql.ndb_binlog_index
09-18T17:35:02      0      0        0       1       0   0.039 mysql.plugin
09-18T17:35:02      0      0        0       1       0   0.035 mysql.proc
09-18T17:35:02      0      0        0       1       0   0.013 mysql.procs_priv
09-18T17:35:02      0      0        1       1       0   0.014 mysql.proxies_priv
09-18T17:35:02      0      0        0       1       0   0.014 mysql.servers
09-18T17:35:02      0      0        0       1       0   0.014 mysql.tables_priv
09-18T17:35:02      0      0        0       1       0   0.015 mysql.time_zone
09-18T17:35:02      0      0        0       1       0   0.015 mysql.time_zone_leap_second
09-18T17:35:02      0      0        0       1       0   0.014 mysql.time_zone_name
09-18T17:35:02      0      0        0       1       0   0.014 mysql.time_zone_transition
09-18T17:35:02      0      0        0       1       0   0.014 mysql.time_zone_transition_type
09-18T17:35:02      0      1        4       1       0   0.015 mysql.user
09-18T17:35:02      0      1        1       1       0   0.014 test.checksums


接下來,來做個案例來測試工具的可用性。

這裏可以分兩種情況

(1)主從數據一致的情況下的比較

(2)模擬主從數據不一致的情況下的比較


首先,我們看第一種主從數據一致的比較

爲了試驗從0做起,這裏我從開始模擬數據
1、登錄master創建模擬需要的庫、表並插入數據
[root@master ~]# mysql -uroot -p123456
mysql> CREATE DATABASE IF NOT EXISTS dbtest;
mysql> USE dbtest;
mysql> CREATE TABLE tb (id int primary key not null auto_increment,name varchar(30),age int) ENGINE=InnoDB;
mysql> INSERT INTO tb(name,age) VALUES ('zhengyansheng','25');
mysql> INSERT INTO tb(name,age) VALUES ('qinheng','24');
mysql> SELECT * FROM tb;
+----+---------------+------+
| id | name          | age  |
+----+---------------+------+
|  1 | zhengyansheng |   25 |
|  2 | qinheng       |   24 |
+----+---------------+------+
 
2、登錄slave查看是否已經同步到數據
[root@slave ~]# mysql -uroot -p123456 -e 'USE dbtest;SELECT * FROM tb;'
+----+---------------+------+
| id | name          | age  |
+----+---------------+------+
|  1 | zhengyansheng |   25 |
|  2 | qinheng       |   24 |
+----+---------------+------+
如果得到這樣的結果,表明主從同步是正常的。
 
3、工具的驗證
pt-table-checksum [OPTIONS] [DSN]
pt-table-checksum:在master上通過執行校驗的查詢對複製的一致性進行檢查,對比主從的校驗值,從而產生結果。DSN指向的是主的地址,該工具的退出狀態不爲零。
 
[root@master ~]# pt-table-checksum --user=root --password=123456 --host=192.168.1.105 --port=3306 --databases=dbtest --tables=tb --nocheck-replication-filters --no-check-binlog-format --replicate=test.checksums
            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
09-18T15:27:05      0      0        2       1       0   0.308 dbtest.tb
 
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參數可以判斷主從數據是否一致。並且也可以通過指定--replicate=rep_test.checksums 參數,就說明把檢查信息都寫到了checksums表中。
進入SLAVE相應的庫中查看checksums表的信息:
[root@slave ~]# mysql -uroot -p123456 -e 'USE test;SELECT * FROM checksums\G;'
Warning: Using a password on the command line interface can be insecure.
*************************** 1. row ***************************
            db: dbtest
           tbl: tb
         chunk: 1
    chunk_time: 0.001182
   chunk_index: NULL
lower_boundary: NULL
upper_boundary: NULL
      this_crc: 5ede99f4    #從的
      this_cnt: 2           #從的
    master_crc: 5ede99f4    #主的
    master_cnt: 2           #主的
            ts: 2015-09-18 15:27:04
             
通過上面的 this_crc <> master_crc 更能清楚的看出他們的不一致了,通過chunk知道是這個張表的哪個塊上的記錄出現不一致。

其次,我們來看主從數據不一致的情況

1、登錄slave主機,手動向dbtest數據庫中的tb表插入一條數據
[root@slave ~]# mysql -uroot -p123456 -e 'USE dbtest; INSERT INTO tb(name,age) VALUES ("liyuntang",25);'
[root@slave ~]# mysql -uroot -p123456 -e 'USE dbtest; SELECT * FROM tb;'
+----+---------------+------+
| id | name          | age  |
+----+---------------+------+
|  1 | zhengyansheng |   25 |
|  2 | qinheng       |   24 |
|  3 | liyuntang     |   25 |
+----+---------------+------+
 
2、用工具驗證
[root@master ~]# pt-table-checksum --user=root --password=123456 --host=192.168.1.105 --port=3306 --databases=dbtest --tables=tb --nocheck-replication-filters --no-check-binlog-format --replicate=test.checksums
            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
09-18T15:41:16      0      1        2       1       0   0.013 dbtest.tb
 
這個時候在DIFFS的值就編程1了,表示主從已經不同步了。如果看更具體的可以在slave主機的查看
[root@slave ~]# mysql -uroot -p123456 -e 'USE test;SELECT * FROM checksums\G;'
*************************** 1. row ***************************
            db: dbtest
           tbl: tb
         chunk: 1
    chunk_time: 0.000746
   chunk_index: NULL
lower_boundary: NULL
upper_boundary: NULL
      this_crc: 4b6ecf1    #從
      this_cnt: 3
    master_crc: 5ede99f4   #主
    master_cnt: 2
            ts: 2015-09-18 15:41:16
這裏你會發現this-crc和master_crc的值已經不一樣的,說明主從數據庫不一致。


四、介紹pt-table-sync

用法:pt-table-sync [OPTIONS] DSN [DSN]

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


方式1:

先master的IP地址,在slave的IP地址
# pt-table-sync --replicate=test.checksums --charset=utf8 h=127.0.0.1,u=root,p=123456,P=3306 h=192.168.1.106,u=root,p=123456,P=3306 --print
# pt-table-sync --replicate=test.checksums --charset=utf8 h=127.0.0.1,u=root,p=123456,P=3306 h=192.168.1.106,u=root,p=123456,P=3306 --execute


方式2:

通過--sync-to-master參數指定一個slave的IP地址就可以了
# pt-table-sync --replicate=test.checksums --databases=dbtest --tables=tb --charset=utf8 --sync-to-master h=192.168.1.106,u=root,p=123456,P=3306 --print
# pt-table-sync --replicate=test.checksums --databases=dbtest --tables=tb --charset=utf8 --sync-to-master h=192.168.1.106,u=root,p=123456,P=3306 --execute


參數的意義

--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      		:密碼。
--ask-pass			: 交互式輸入密碼。	
--print       		:打印,但不執行命令。
--execute     		:執行命令。


該工具檢查的表,需要檢查連接的帳號需要有很高的權限,在一般權限行需要加SELECT, PROCESS, SUPER, REPLICATION SLAVE等權限,測試方便我直接給了ALL的權限,pt-table-checksum 和 pt-table-sync 一起互補使用


錯誤彙總

錯誤1:
Can't make changes on the master because no unique index exists at /usr/bin/pt-table-sync line 10660
原因是:表中沒有唯一索引或則主鍵則會報錯

錯誤2:
09-14T18:04:36 install_driver(mysql) failed: Attempt to reload DBD/mysql.pm aborted.
Compilation failed in require at (eval 23) line 3.

 at /usr/bin/pt-table-checksum line 1581
解決辦法:
ln -sv /usr/lib64/mysql/libmysqlclient.so.16 /lib64/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章