MySQL-主從一致校驗


1. 場景需求

      2020年春,由我司開發的考試系統項目,經過不懈的運營努力,用戶群體每日以指數倍激增,現考慮到數據庫的安全可靠和訪問性能問題,決定在業務中集成部署Mysql主從復制以實現讀寫分離等功能;巧的是,在想要進行主從復制操作前,我們的主要業務數據庫已經工作了一段時間,現在要添加一台新的從數據庫進行主從復制,通過一位發量稀少同事的一番操作,兩台主機已經成功部署好了主從復制,但是我們該如何檢測主從服務器的數據是否一致,如果不一致怎么同步數據?

2. 參考答案

      我們可以通過采用pt-table-checksum工具來檢查主從的一致性,以下是具體流程。

  1. 工具安裝

[root@MySQL-01 ~]# wget http://www.percona.com/get/percona-toolkit.tar.gz

  1. 安裝所需依賴

[root@MySQL-01 ~]# yum install perl perl-devel perl-Time-HiRes perl-DBI perl-DBD-MySQL

perl-Compress-Raw-Bzip2

perl-Compress-Raw-Zlib

perl-Digest

perl-Digest-MD5

perl-IO-Compress

perl-IO-Socket-IP

perl-IO-Socket-SSL

perl-Mozilla-CA

perl-Net-Daemon

perl-Net-LibIDN

perl-Net-SSLeay

...

  1. 安裝工具

[root@MySQL-01 ~]# tar zxf percona-toolkit-2.2.13.tar.gz

[root@MySQL-01 ~]# cd percona-toolkit-2.2.13

[root@MySQL-01 ~]# perl Makefile.PL

[root@MySQL-01 ~]# make && make install

  1. 在進行主從校驗之前,我們首先需要對主從庫進行授權,來看看如何來做吧

主庫授權

root@node1 12:28:  [pt_check]> GRANT CREATE,INSERT,SELECT,DELETE,UPDATE,LOCK TABLES,PROCESS,SUPER,REPLICATION SLAVE ON *.* TO 'root'@'47.97.218.145' IDENTIFIED BY '123456';

Query OK, 0 rows affected (0.00 sec)

root@node1 12:29:  [pt_check]>  flush privileges;

Query OK, 0 rows affected (0.00 sec)

root@node1 12:29:  [pt_check]> select Host,User  from mysql.user;

+----------------+---------------+

| Host         | User        |

+---------------------+--------------------+

| localhost      | root          |

| localhost      | mysql.session  |

| localhost      | mysql.sys      |

| 172.16.156.%   | rep           |

| %            | java          |

| 192.168.1.101   | ptuser        |

+----------------------+---------------------+

從庫授權

MariaDB [(none)]> GRANT SELECT, PROCESS, SUPER, REPLICATION SLAVE ON *.* TO 'root'@'9.106.84.122' IDENTIFIED BY '123456';

Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> flush privileges;

Query OK, 0 rows affected (0.00 sec)

授權到主從兩個數據庫之后呢,我們就可以開開心心的,進行主從數據一致性的校驗。且看下面

pt-table-checksum是通過在主(master)上通過執行校驗的查詢對復制的一致性進行檢查,對比主從的校驗值,從而產生結果。

DSN指向的是主的地址,該工具的退出狀態不為零,如果發現有任何差別,或者如果出現任何警告或錯誤,可以查看官方資料。

現在有一主庫,數據如下:

mysql> select *  from yayun.t1;

+----+-------+

| id | name |

+----+-------+

|  1 | yayun|

|  2 | atlas |

|  3 | mysql |

+----+-------+

3 rows in set (0.00 sec)

# 主庫有三條數據

       而從庫的數據於主庫是不一致的,我們來欣賞下從庫不一致的數據:

mysql> select * from yayun.t1;

+----+----------+

| id | name  |

+----+----------+

|  1 | yayun |

|  2 | atlas  |

|  3 | mysql  |

|  4 | dengyy |

|  5 | love sql |

+----+----------+

5 rows in set (0.00 sec)

# 從庫有五條數據,多了倆條不一樣的:4、5

      接下來,我們通過工具進行檢測:

[root@MySQL-01 ~]# pt-table-checksum --nocheck-binlog-format --nocheck-replication-filters --replicate=pt.checksums  --databases test -u'root' -p'123456' -h127.0.0.1 -P3306

      命令會展示如下的結果

          TS  ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE

04-13T15:59:31        0      1         3         1        0      0.080 yayun.t1

      其中如上表所示的結果中,各字段解釋如下

TS

完成檢查的時間

ERRORS

檢查時候發生錯誤和警告的數量

DIFFS

0表示一致,1表示不一致

ROWS

表的行數

CHUNKS

被划分到表中的塊的數目

SKIPPED

由於錯誤或警告或過大,則跳過塊的數目

TIME

執行的時間

TABLE

被檢查的表名

       清晰的看到,當主從之間數據不一致時,進行一致性檢查看到的結果DIFF為1。此時代表一致性是錯誤的。

      上面命令的各參數的意思在這里也做好事做到底來解釋一下:

--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=yayun.checksums 參數,就說明把檢查信息都寫到了checksums表中。

       進入SLAVE相應的庫中查看checksums表的信息:

mysql> select * from checksums\G

*************************** 1. row ***************************

            db: yayun

           tbl: t1

         chunk: 1

    chunk_time: 0.010735

   chunk_index: NULL

lower_boundary: NULL

upper_boundary: NULL

      this_crc: babf1dc0    #slave

      this_cnt: 5           #slave

    master_crc: 8727436a    #master

    master_cnt: 3           #master

       # 可以發現表t1中從庫比主庫多2條記錄

    ts: 2014-04-13 16:05:16

1 row in set (0.00 sec)

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

       這個命令的使用很簡單,他的語法是這個:pt-table-sync [OPTIONS] DSN [DSN]。pt-table-sync,高效的同步MySQL表之間的數據,他可以做單向和雙向同步的表數據;他可以同步單個表,也可以同步整個庫。

       它不同步表結構、索引、或任何其他模式對象。所以在修復一致性之前需要保證他們表存在。

      接着上面的復制情況,主和從的t1表數據不一致,需要修復,首先執行:

[root@MySQL-01 ~]# pt-table-sync --replicate=pt.checksums h=47.97.218.145,u=root,p=123456 h=39.106.84.122,u=root,p=123456 --print

 

DELETE FROM `yayun`.`t1` WHERE `id`='4' LIMIT 1 /*percona-toolkit src_db:yayun src_tbl:t1 src_dsn:h=127.0.0.1,p=...,u=root dst_db:yayun dst_tbl:t1 dst_dsn:h=192.168.0.20,p=...,u=root lock:1 transaction:1 changing_src:yayun.checksums replicate:yayun.checksums bidirectional:0 pid:2190 user:root host:MySQL-01*/;

DELETE FROM `yayun`.`t1` WHERE `id`='5' LIMIT 1 /*percona-toolkit src_db:yayun src_tbl:t1 src_dsn:h=127.0.0.1,p=...,u=root dst_db:yayun dst_tbl:t1 dst_dsn:h=192.168.0.20,p=...,u=root lock:1 transaction:1 changing_src:yayun.checksums replicate:yayun.checksums bidirectional:0 pid:2190 user:root host:MySQL-01*/;

      參數的意義:

--replicate=  :指定通過pt-table-checksum得到的表,這2個工具差不多都會一直用。

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

--tables=     :指定執行同步的表,多個用逗號隔開。

--sync-to-master :指定一個DSN,即從的IP,他會通過show processlist或show slave status 去自動的找主。

h=127.0.0.1   :服務器地址,命令里有2個ip,第一次出現的是Master的地址,第2次是Slave的地址。

u=root             :帳號。

p=123456    :密碼。

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

--execute     :執行命令。

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

[root@MySQL-01 ~]# pt-table-sync --replicate=pt.checksums h=47.97.218.145,u=root,p=123456 h=39.106.84.122,u=root,p=123456 --execute

      沒發現任何異常,然后檢查主從數據的一致性:

[root@MySQL-01 ~]# pt-table-checksum --nocheck-binlog-format --nocheck-plan --nocheck-replication-filters --replicate=pt.checksums --set-vars innodb_lock_wait_timeout=120 --databases test -u'root' -p'123456' -h47.97.218.145 -P3306

          TS     ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE

04-13T16:27:28            0      0          3         1        0     0.097 yayun.t1

      再來看看對應的數據庫吧:

主庫

mysql> select * from t1;

+----+-------+

| id | name  |

+----+-------+

|  1 | yayun |

|  2 | atlas |

|  3 | mysql |

+----+-------+

3 rows in set (0.00 sec)

mysql>

從庫會丟失掉之前多余的兩條數據

mysql> select * from t1;

+----+-------+

| id | name  |

+----+-------+

|  1 | yayun |

|  2 | atlas |

|  3 | mysql |

+----+-------+

3 rows in set (0.00 sec)

      OK,數據已經保持一致了。

       不過來自1902a班的張磊建議還是用—print 打印出來的好,這樣就可以知道那些數據有問題,可以人為的干預下。不然直接執行了,出現問題之后更不好處理。總之還是在處理之前做好數據的備份工作。

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

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

       最后,這些工具很給力,工作中常常在使用。注意使用該工具需要授權,一般SELECT, PROCESS, SUPER, REPLICATION SLAVE等權限就已經足夠了。


免責聲明!

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



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