mysql主主同步,主從同步數據不一致問題解決


問題起源:

  1. mysql數據庫同步過程中經常會因為某種錯誤導致同步出錯而暫停,此時使用show slave status\G命令能查看到錯誤數據此時Slave_SQL_Running: No,為了解決這個問題一般使用如下命令解決
stop slave;
set global sql_slave_skip_counter =1;
start slave;  

有時候忽略一次錯誤還不行,需要忽略很多,那么忽略錯誤過程中就會出現數據不一致的問題(有些正常數據被忽略了)

  1. 某個服務器異常宕機導致部分SQL未同步

如何解決:

為了保證不同mysql服務器之間的數據一致,可以采用如下的一個工具集合Percona-toolkit
他有2個工具:pt-table-checksumpt-table-sync
pt-table-checksum:用於檢測2個數據庫之間哪些表的數據不一致
pt-table-sync:用於修復數據不一致的表或者庫

這里需要注意的地方是:必須選擇一個庫作為參考,強烈建議選擇主庫作為參考,主庫和從庫數據不一致時把主庫的數據同步到從庫達到一致。如果既要把主庫的部分表同步到從庫 又要想把從庫的部分數據同步到主庫(主主同步時會有此需求)則需要采取特殊手段,后面有說明

第一步:安裝工具集Percona-toolkit

工具集請安裝在主庫的服務器上面

#安裝依賴包
yum install perl perl-DBI perl-DBD-MySQL perl-IO-Socket-SSL perl-Time-HiRes perl-Digest-MD5 perl-ExtUtils-MakeMaker -y
#下載工具集
wget https://www.percona.com/downloads/percona-toolkit/2.2.18/tarball/percona-toolkit-2.2.18.tar.gz 
#解壓縮
tar -xvf percona-toolkit_2.2.18.tar.gz
#進入目錄
cd percona-toolkit-2.2.18/
#執行perl腳本
perl Makefile.PL
#編譯
make
#安裝
make install

第二步:執行命令進行檢測

通過使用pt-table-checksum命令來進行檢測,注意檢測時需要指定一個表(表名可自定義),這個表用來記錄差異點 為后續同步數據作為參考,這里假設要檢測test數據庫里面的table1表是否不同步。
pt-table-checksum --nocheck-binlog-format --nocheck-replication-filters --replicate=test.checksums --databases=test --tables=table1 --host=172.16.0.21 --port=3306 --user=check_user --password=123456
關於以上命令的解釋如下:

--nocheck-replication-filters :不檢查復制過濾器,建議啟用,這樣我們可以自定義檢查哪個數據庫的數據,否則將會檢查mysql所有被同步的數據庫。
--no-check-binlog-format      : 不檢查復制的binlog模式,要是binlog模式是ROW,則會報錯。
--replicate-check-only :只顯示不同步的信息,根據情況可加可不加,不加就會顯示全部表的信息。
--replicate=    :把checksum的信息寫入到指定表中,建議直接寫到被檢查的數據庫當中。 
--databases=    :指定需要被檢查的數據庫,多個則用逗號隔開,建議一個一個檢查。
--tables=       :指定需要被檢查的表,多個用逗號隔開
--host=         :Master的地址
--user=         :用戶名,也可以使用root用戶,或者自己創建用戶賦予查詢,修改,刪除,同步權限,注意數據庫權限也要賦予
--password=     :密碼
--Port=         :端口

在主庫服務器執行以上命令之后 test數據庫里面多了一個表checksums記錄了哪些表不同步的信息。同時執行命令后命令輸出如下信息:

# A software update is available:
#   * The current version for Percona::Toolkit is 3.0.5

            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
09-02T11:59:07      0      1  1266622      14       0   5.983 test.table1
[root@db-001-server ~]# 

部分字段的解釋如下

TS            :完成檢查的時間。
ERRORS        :檢查時候發生錯誤和警告的數量。
DIFFS         :0表示一致,1表示不一致。當指定--no-replicate-check時,會一直為0,當指定--replicate-check-only會顯示不同的信息。
ROWS          :表的行數。
CHUNKS        :被划分到表中的塊的數目。
SKIPPED       :由於錯誤或警告或過大,則跳過塊的數目。
TIME          :執行的時間。
TABLE         :被檢查的表名。

以上結果中DIFFS為1代表主庫和從庫之間的數據有差異,接下來就是如何修復差異數據,我們使用另一個命令:pt-table-sync

pt-table-sync h=172.16.0.21,u=check_user,p=123456,P=3306 --databases=test --tables=table1 --replicate=test.checksums --print

上面命令里面的參數和之前的pt-table-checksum命令里面的一樣,只是使用了簡寫的方式,注意最后一個參數 --print 這個很重要 這個--print會先把要執行修復操作的SQL文打印出來並不真正執行,用戶可以查看SQL文。這里需要說一下 pt-table-sync修復數據差異的原理:
這個命令首先會根據pt-table-checksum命令比較的結果也就是checksums表的記錄去自動生成相關的SQL文,比如主庫表里面多了一條記錄則會生成一個SQL文 類似於 replace into table1(xx,xx,xx) values(yy,yy,yy)
這里使用replace into就是有記錄則刪除再插入,無記錄則直接插入,這樣一來主庫執行了該條SQL之后記錄不變,但是因為主從同步的原因從庫也會執行這條記錄,這樣就能夠達到主庫和從庫數據一致了。需要注意一個前提就是表必須有主鍵才行
如果主庫里面沒有了某條記錄而從庫里面還有記錄 因為我們要參考主庫作為最終依據則此時使用命令會生成DELETE FROM TABLE1 WHERE ID = XX的SQL文(記住這個原理,后續有用處)

如果確認SQL沒問題想執行修復 只需要執行如下語句(把--print替換成了 --execute)

pt-table-sync h=172.16.0.21,u=check_user,p=123456,P=3306 --databases=test --tables=table1 --replicate=test.checksums --execute

修復完畢之后可以重新執行一下pt-table-checksum命令看是否一致了。

以上便是解決主從不同步的方式,如果想要解決多張表則只需要在--tables后面指定多張表,如果想要修復整個庫則只需要去掉--tables則默認檢查整個數據庫的所有表

主主同步留下的一個問題:如果部分表想要參考另一個庫的數據,該如何做?

這個問題是我自己親身遇到的,我的mysql數據庫做的是主主同步,A,B兩個數據庫互為主庫雙向同步。因此發現數據不一致時需要保持兩個庫的數據匯總操作
我是這樣解決的:
首先在A庫服務器上面執行完pt-table-checksum之后執行pt-table-sync發現里面有DELETE SQL文,意思是要刪除某些數據,因為此時A庫里面部分數據比B庫少,那么怎么辦呢,這里我單獨提取了DELETE SQL文的主鍵,然后去B庫查詢這些數據並復制成INSERT 語句(使用Navicat工具的同學應該知道有這個功能,把查詢到的數據復制成插入SQL文),然后我把這些插入SQL文改成replace into的方式(只需要替換insert為replace即可) 然后在B庫執行這些SQL文,此時A庫的這個表就擁有這些數據了。
那么重新執行pt-table-checksum之后執行pt-table-sync 打印出來的SQL文只剩下replace into了 這時可以放心執行修復了。這只是一種思路用於數據量不大的情況。如果數據量大該怎么辦呢?可以在B庫服務器安裝工具集然后執行同樣的操作並且復制出replace into sql文在B庫執行。A B2個庫來回切換着同步一樣可以解決問題。


免責聲明!

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



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