1. 程式人生 > >mysql(五)------針對主從同步的情況兩個庫進行數據校對及恢復

mysql(五)------針對主從同步的情況兩個庫進行數據校對及恢復

ges eth 開始 效率 ack isam ipp 完成 mobile

兩臺MySQL,發生了種種種種,導致了兩個表的數據不一致,但是同步還在正常進行,後來意識到這種問題(可能之前skip啊,或者一開始搭建的時候就是不一致的狀態),該如何修復呢?
如果數據量小的情況可以考慮從新導數據,如果數據量很大的話,那就太要命了
於是可以用percona-toolkit這個工具修復並並檢查這種情況的
再主備同步的時候在進行如下操作:
在主庫上安裝pt-table-checksum
安裝:

1.安裝軟件包:
# yum install perl perl-devel perl-Time-HiRes perl-DBI perl-DBD-MySQL
2.安裝工具percona-toolkit
  # yum install http://www.percona.com/downloads/percona-release/redhat/0.1-4/percona-release-0.1-4.noarch.rpm
# yum list | grep percona-toolkit

# yum install percona-toolkit

3.安裝pt-table-checksum
?# wget?http://www.percona.com/get/percona-toolkit.tar.gz

4.解壓並安裝
# tar zxvf percona-toolkit.tar.gz
# cd percona-toolkit-3.0.13
# perl Makefile.PL
#   make && make install
安裝完成後:
# pt-table-checksum
# pt-table-sync 檢查安裝是否成功

技術分享圖片

如果報:
erl: relocation error: /usr/lib64/perl5/vendor_perl/auto/DBD/mysql/mysql.so
如有報錯:
DBD::mysql::db do failed: Access denied; you need (at least one of) the SUPER privilege(s) for this operation [for Statement "/*!50105 SET @@binlog_format="STATEMENT"*/"] at /usr/local/bin/mk-table-sync line 8568.
Issuing rollback() due to DESTROY without explicit disconnect() of DBD::mysql::db handle ;host=192.168.1.101;port=3306;mysql_read_default_group=client at /usr/local/bin/mk-table-sync line 8568.
解決辦法:安裝DBI和DBD-MySQL
下載地址:
http://ftp.cuhk.edu.hk/pub/packages/perl/CPAN/authors/id/T/TI/TIMB/
http://search.cpan.org/dist/DBD-mysql/?
或者百度雲盤下載:https://pan.baidu.com/s/1miv0S8g?(提取密碼:fh24)
[[email protected] src]# tar -zvxf DBI-1.634.tar.gz?
[[email protected] src]# cd DBI-1.634
[[email protected] DBI-1.634]# perl Makefile.PL
[[email protected] DBI-1.634]# make && make install
[[email protected] src]# tar -zvxf DBD-mysql-4.041_01.tar.gz?
[[email protected] src]# cd DBD-mysql-4.041_01
[[email protected] DBD-mysql-4.041_01]# perl Makefile.PL --mysql_config=/usr/local/mysql/bin/mysql_config ? ? ? ??//主庫mysql安裝路徑/usr/local/mysql
[[email protected] DBD-mysql-4.041_01]# make
[[email protected] DBD-mysql-4.041_01]# make install

5.在主數據庫master上建立用戶並授權
    CREATE USER ‘test‘ IDENTIFIED BY "test";
    grant all privileges on *.* to ‘test‘ identified by ‘test‘;
    flush privileges;

技術分享圖片

6.檢測下test是否可以登錄

7.但是我們檢查使用的mysql用戶一般是沒有 create table 權限的,所以你可能需要先手動創建:
CREATE DATABASE IF NOT EXISTS percona;CREATE TABLE IF NOT EXISTS percona.checksums (
    db CHAR(64) NOT NULL,
    tbl CHAR(64) NOT NULL,
    chunk INT NOT NULL,
    chunk_time FLOAT NULL,
    chunk_index VARCHAR(200) NULL,
    lower_boundary TEXT NULL,
    upper_boundary TEXT NULL,
    this_crc CHAR(40) NOT NULL,
    this_cnt INT NOT NULL,
    master_crc CHAR(40) NULL,
    master_cnt INT NULL,
    ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (db,tbl,chunk),
    INDEX ts_db_tbl(ts,db,tbl)
) ENGINE=InnoDB;

8.生產環境中數據庫用戶權限一般都是有嚴格管理的,假如連接用戶是repl_user(即直接用復制用戶來檢查),它應該額外賦予對其它庫的 SELECT ,LOCK TABLES 權限,如果後續要用 pt-table-sync 就就需要寫權限了。對percona庫有寫權限:
   GRANT ALL PRIVILEGEES on percona.* to [email protected]‘%‘ IDENTIFIED BY ‘repl_pass‘;
    GRANT SELECT,LOCK TABLES,PROCESS,SUPER on *.* to [email protected]‘%‘;

註:
a.為了減少不必要的麻煩,確保你的 [email protected]‘xxx‘ 用戶能同時登陸主庫和從庫
b.--create-replicate-table?選項會自動創建 percona.checksums 表,但也意味著賦予額外的?CREATE TABLE權限給 [email protected]‘xxx‘ 用戶。默認yes
c.PROCESS用於自動發現從庫信息,SUPER權限用於set binlog_format。
d.--no-check-replication-filters?表示不需要檢查 Master 配置裏是否指定了 Filter。 默認會檢查,如果配置了 Filter,如      replicate_do_db,replicate-wild-ignore-table,binlog_ignore_db 等,在從庫checksum就與遇到表不存在而報錯退出,所以官方默認是yes(--check-replication-filters)但我們實際在檢測中時指定--databases=,所以就不存在這個問題,幹脆不檢測
e.--empty-replicate-table:每個表checksum開始前,清空它之前的檢測數據(不影響其它表的checksum數據),默認yes。當然如果使用--resume啟動檢測數據不會清空。
當啟用--noempty-replicate-table即不清空時,不計算計算chunk,只計算。
f.--databases=,-d:要檢查的數據庫,逗號分隔。用腳趾頭想也知道?--databases-regex?正則匹配要檢測的數據庫,--ignore-databases[-regex]忽略檢查的庫。Filter選項。
g.--tables=,-t:要檢查的表,逗號分隔。如果要檢查的表分布在不同的db中,可以用--tables=dbname1.table1,dbnamd2.table2的形式。同理有--tables-regex,--ignore-tables,--ignore-tables-regex。--replicate指定的checksum表始終會被過濾。
h.--recursion-method:發現從庫的方式。pt-table-checksum 默認可以在主庫的?processlist中找到從庫復制進程,從而識別出有哪些從庫,但如果使用是非標準3306端口,會導致找不到從庫信息。此時就會自動采用host方式,但需要提前在從庫 my.cnf 裏面配置report_host、report_port信息,如:
    report_host = MASTER_HOSt report_port = 1330
最終極的辦法是dsn,dsn指定的是某個表(如 percona.dsns ),表行記錄是改主庫的(多個)從庫的連接信息。適用以下任一情形:
主庫不能自動發現從庫
不想在從庫添加額外配置(因為要重啟)
主從檢測連接用戶信息不一樣
多個從庫時只想驗證指定從庫的一致
我比較傾向使用DSN的方式。這個dsns表只需要在執行?pt-table-checksum?命令的服務器上能夠訪問到就行。這裏糾正一個認識,網上很多人說 pt-table-checksum 要在主庫上執行,其實不是的,我的mysql實例比較多,只需在某一臺服務器上安裝percona-toolkit,這臺服務能夠同時訪問主庫和從庫就行了。具體用法見後面實例。

9.

pt-table-checksum註意事項:
a.? 根據測試,需要一個即能登錄主庫,也能登錄從庫的賬號;
b.? 只能指定一個host,必須為主庫的IP;
c.? 在檢查時會向表加S鎖;
d.如果master和slave的binlog日誌不是STATEMENT格式,要用--no-check-binlog-format選項
e.? 運行之前需要從庫的同步IO和SQL進程是YES狀態。
f.?表要有主鍵索引或唯一鍵索引

10.安裝完成測試:

11.在主庫上(master:3306),如下:
   Select * from t1.student;

技術分享圖片

12.在從庫上(slave:3306),如下:
Select * from t1.student;

技術分享圖片

校驗:
pt-table-checksum h=10.1.31.78,u=test,p=‘test‘,P=3306 --databases=t1   --nocheck-replication-filters --no-check-binlog-format

技術分享圖片

TS :完成檢查的時間。
ERRORS :檢查時候發生錯誤和警告的數量。
DIFFS :0表示一致,1表示不一致。當指定--no-replicate-check時,會一直為0,當指定--replicate-check-only會顯示不同的信息。
ROWS :表的行數。
CHUNKS :被劃分到表中的塊的數目。
SKIPPED :由於錯誤或警告或過大,則跳過塊的數目。
TIME :執行的時間。
TABLE :被檢查的表名。
常見錯誤
h.Diffs cannot be detected because no slaves were found
不能自動找到從庫,確認processlist或host或dsns方式用對了。
i.Cannot connect to h=slave1.*.com,p=...,u=percona_user
可以在pt-table-checksum命令前加PTDEBUG=1來看詳細的執行過程,如端口、用戶名、權限錯誤。
j.Waiting for the --replicate table to replicate to XXX
問題出在 percona.checksums 表在從庫不存在,根本原因是沒有從主庫同步過來,所以看一下從庫是否延遲嚴重。
k.Pausing because Threads_running=25
反復打印出類似上面停止檢查的信息。這是因為當前數據庫正在運行的線程數大於默認25,pt-table-checksum 為了減少對庫的壓力暫停檢查了。等數據庫壓力過了就好了,或者也可以直接 Ctrl+C 終端,下一次加上--resume繼續執行,或者加大--max-load=值。
l.字符集問題
Error checksumming table Error executing checksum query: DBD::mysql::st execute failed: Illegal mix of collations
12-17T14:48:04 Error checksumming table d_ec_cs.t_online_cs: Error executing checksum query: 
DBD::mysql::st execute failed: Illegal mix of collations for operation ‘concat_ws‘ [for Statement "REPLACE INTO `percona`.`ali_checksum` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT ?, ?, ?, ?, ?, ?, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS(‘#‘, `f_cs_id`, `f_corp_id`, `f_valid`, `f_show_name`, `f_online_msg`, `f_offline_msg`, `f_show_mobile`, `f_group_id`, `f_qq`, `f_show_qq`, `f_msn`, `f_show_msn`, `f_sms_online`, `f_scheme`, `f_tel`, `f_telno`, `f_show_tel`, `f_contact`, `f_mobile`, `f_position`, `f_other1`, `f_other2`, `f_other_text1`, `f_other_text2`, `f_email`, `f_qq_first`, `f_qq_first_type`, `f_aids_open`, `f_aids_qq`, `f_aids_crmqq`, `f_aids_yahoo`, `f_aids_skype`, `f_aids_aliww`, `f_aids_msn`, `f_aids_alibaba`, `f_aids_alitrade`, CONCAT(ISNULL(`f_show_name`), ISNULL(`f_group_id`), ISNULL(`f_qq`), ISNULL(`f_show_qq`), ISNULL(`f_sms_online`), ISNULL(`f_other_text1`), ISNULL(`f_other_text2`), ISNULL(`f_email`)) )) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `d_ec_cs`.`t_online_cs` 
/*checksum table*/" with ParamValues: 0=‘d_ts_profile‘, 1=‘t_user_account‘, 2=1, 3=undef, 
沒找到解決辦法

備庫插入幾筆數據
技術分享圖片
技術分享圖片

再次校驗:
 pt-table-checksum h=10.1.31.78,u=test,p=‘test‘,P=3306 --databases=t1   --nocheck-replication-filters --no-check-binlog-format

技術分享圖片

錯10 ROWS

這時用pt-table-sync修復
i.自動消除差異(不推薦)
pt-table-sync --print --execute --sync-to-master?h=10.1.31.77,P=3306,u=checksums,p=‘checksums‘ --databases=newtables --tables=tb1

ii.打印出sql語句,人工幹預到Slave庫執行(推薦)

pt-table-sync --print --sync-to-master?h=10.1.31.77,P=3306,u=checksums,p=‘checksums‘ --databases=newtables?--tables=tb1
或
pt-table-sync --print --sync-to-master?h=10.1.31.77,P=3306,u=checksums,p=‘checksums‘--replicate pt.checksums

#--sync-to-master :?指定一個DSN,即從的IP,他會通過show processlist或show slave status 去自動的找主。
#--replicate :指定通過pt-table-checksum得到的表,這2個工具差不多都會一直用。
#--print :打印,但不執行命令。
#--execute ?:執行命令。

備註:Slave需要授權主庫Drop 和Create Temporary Tables權限

8.檢驗
重新執行一次pt-table-checksum,查看是否還存在差異。

四、註意事項
1.采用replace into來修復主從不一致,必須保證被replace的表上有主鍵或唯一鍵,否則replace into退化成insert into,起不到修復的效果。這種情況下pt-table-sync會采用其他校驗和修復算法,但是效率非常低,例如對所有列的group by然後求count(*)(表一定要有主鍵!)。
2.主從數據不一致需要通過replace into來修復,該sql語句必須是語句級。pt-table-sync會把它發起的所有sql語句都設置為statement格式,而不管全局的binlog_format值。這在級聯A-B-C結構中,也會遇到pt-table-checksum曾經遇到的問題,引起行格式的中繼庫的從庫卡庫是必然。不過pt-table-sync默認會無限遞歸的對從庫的binlog格式進行檢查並警告。
3.由於pt-table-sync每次只能修復一個表,所以如果修復的是父表,則可能導致子表數據連帶被修復,這可能會修復一個不一致而引入另一個不一致;如果表上有觸發器,也可能遇到同樣問題。所以在有觸發器和主外鍵約束的情況下要慎用。pt-table-sync工具同樣也不歡迎主從異構的結構。pt-table-sync工具默認會進行先決條件的檢查。

4.pt-table-sync在修復過程中不能容忍從庫延遲,這正好與pt-table-checksum相反。如果從庫延遲太多,pt-table-sync會長期持有對chunk的for update鎖,然後等待從庫的master_pos_wait執行完畢或超時。從庫延遲越大,等待過程就越長,主庫加鎖的時間就越長,對線上影響就越大。因此要嚴格設置max-lag。

5.對從庫數據的修復通常是在主庫執行sql來同步到從庫。因此,在有多個從庫時,修復某個從庫的數據實際會把修復語句同步到所有從庫。數據修復的代價取決於從庫與主庫不一致的程度,如果某從庫數據與主庫非常不一致,舉例說,這個從庫只有表結構,那麽需要把主庫的所有數據重新灌一遍,然後通過binlog同步,同時會傳遞到所有從庫。這會給線上帶來很大壓力,甚至拖垮集群。正確的做法是,先用pt-table-checksum校驗一遍,確定不一致的程度:如果不同步的很少,用pt-table-sync直接修復;否則,用備份先替換它,然後用pt-table-sync修復。 說明: 這實際提供了一種對myisam備份的思路:如果僅有一個myisam的主庫,要為其增加從庫,則可以:先mysqldump出表結構到從庫上,然後啟動同步,然後用pt-table-sync來修復數據。

mysql(五)------針對主從同步的情況兩個庫進行數據校對及恢復