主從的一致性校驗node
場景:mysql
有人會問道:如何驗證主從的一致性面試
又或者問:一個庫裏有幾十張表 主從結構數據是否一致?sql
簡單來說能夠在低峯期主從上分別使用select count(*)來看一下,這種方式是最古老的,準確度不是很高數據庫
盜貼 麻煩 說一聲,本文來自 yijiu.blog.51cto.comsession
主流方法:ide
使用pt-table-checksum驗證主從的一致性函數
盜貼 麻煩 說一聲,本 文l來自 yijiu.blog.51cto.comui
Pt-table-checksum的工做流程:this
在某些數據不超過1千行則馬上顯示出;若是超過1千行,會進行分段,至於如何分段其內部有特定機制
計算以後會在主庫建一個表。默認表名爲checksums
生成表後將session 會話級別的binlog格式改成語句級別格式,然後對每張表進行如下語句:
select .. count (*), bit_xor(crc32(#id#col1#col2...))from tb where id > xxx and id <xxxx;
然後執行如下函數
#主要是將一個列拼成了一個用#號隔開的字符串
replace into checksums select .. count(*), bit_xor(crc32(#id#col1#col2...))from tb where id>xxx and id <xxxx;
將語句所有寫到checksums表中,這樣若是主庫執行了crc32函數的話,那麼從庫再執這些列進行crc32匹配,若是值不同的話,則數據不一致
由於語句級的複製,只是將語句傳遞到不一樣的庫去執行,這樣的話無論有多少個從庫都會將在主庫將此語句跑完然後在從庫上也執行此條語句並在從庫執行
執行完後將語句所有寫chechksums中,然後經過pt-table-checksum去讀這個表,是否跟主庫的crc32去對比,若是不同則認爲數據是不正確的,並且會分段列出,然後嘗試修復
pt-table-checksum修復的過程
依舊將語句改成行格式,然後在主庫執行replace into,其做用是主要修復主庫上存在的語句,而從庫沒有的數據,或者主從都有主鍵,可是從庫和主庫的數據有衝突
另一種是從庫存在數據,而主庫沒有數據,則在主庫執行delete操做,然後將語句記錄在binlog中,再將binlog同步到relay log使從庫上刪掉
盜貼 a麻煩 說一d聲,本 文l來自 yijiu.blog.51cto.com
安裝pt-table-checksum
下載pt-table-checksum
wget http://www.percona.com/get/percona-toolkit.tar.gz
或者使用yum安裝,須要指定epel
[root@mysql_node1 ~]# yum install percona-toolkit
pt-table-checksum的參數
--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
盜貼 a麻煩 說一d聲,本 文l來自 yijiu .blo g.51cto.com
--recursion-method=processlist
執行結果顯示參數意義:
TS :完成檢查的時間。
ERRORS :檢查時候發生錯誤和警告的數量。
DIFFS :0表示一致,大於0表示不一致。當指定--no-replicate-check時,會一直爲0,當指定--replicate-check-only會顯示不一樣的信息。
ROWS :表的行數。
CHUNKS :被劃分到表中的塊的數目。 好比個表N條記錄,那麼會分紅幾十個chunks 每一個N行的去檢測
SKIPPED :因爲錯誤或警告或過大,則跳過塊的數目。
TIME :執行的時間。
TABLE :被檢查的表名。
例:
pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=testdb.checksums --create-replicate-table --databases=testdb --tables=t5 -h 1.1.1.1 -P 3306 -u testdb -p testdatabase --recursion-method="processlist"
參數解釋:
nocheck-replication-filters #不檢查加載項
no-check-binlog-format 不檢查binlog
replicate = testdb.checksums #checksums表在哪一個庫中
create-replicate-table #上面的庫或表若是不存在則自動建立
databases=testdb #表示檢查哪一個庫,若是檢查整個庫裏面表,那麼後面的--tables=t5 參數能夠去掉,可是生產環境中表不少或者很大,或者天天晚上就跑一張表則須要加下面參數
tables=t5
盜貼 a麻煩 說一w聲,本 文l來自 yijiu .blo g.51cto.com
執行完後最後查看結果,若是是diffs出現大於0則表示不一致
檢測當前數據庫test110庫是否錯誤,並查看結果
[root@mysql_node1 ~]# pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=testdb.checksums --create-replicate-table --databases=test110 -h 10.12.33.61 -P 3306 -u root -p mypass --recursion-method="processlist"
Diffs cannot be detected because no slaves were found. Please read the --recursion-method documentation for information.
TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE
11-12T14:03:11 0 0 1000 1 0 0.016 test110.yw
嘗試模擬出錯並使用pt-table-checksum進行檢測
在從庫刪除某條信息而後再次檢測
在從庫上操做:
首先忽略錯誤
盜貼 a麻煩 說一w聲,本 文al來自 yijiu.blo g.51 cto.com
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
mysql> set global sql_slave_skip_counter = 1;
Query OK, 0 rows affected (0.00 sec)
主庫執行
mysql> call insert_yw(1);
Query OK, 1 row affected (0.01 sec)
開啓從庫
mysql>start slave;
檢測一致性
再次在主庫上執行tp-table-checksum
[root@node1 tools]# pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=testdb.checksums --create-replicate-table --databases=test110 -h 10.12.33.58 -P 3306 -u root -p mypass --recursion-method="processlist"
TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE
11-12T16:40:55 0 1 1011 1 0 0.044 test110.yw
修復不一致
修復不一致能夠直接調用pt-table-sync腳本
pt-table-sync工做流程
首先將sql打印出來,而後再去執行execute
好比,以前的庫發現不一致,那麼接下來使用pt-table-sync進行修復
以下所示
#pt-table-sync --replicate=testdb.checksums --databases=testdb --charset=utf8 h=10.12.33.58,u=testdb,p=testdbtestdb -print
參數解釋:
#指定哪一個庫、字符集以及鏈接進來的DSN
#DSN: h=10.12.33.58,u=testdb,p=testdbtestdb
#-print 表示只打印出來修復的SQL,可是不執行
嘗試修復
pt-table-sync --replicate=testdb.checksums --databases=testdb --charset=utf8 h=10.12.33.58,u=testdb,p=testdbtestdb --execute
#主庫完後在從庫修改數據,並執行checksum
盜貼麻煩 說一w聲,本 文來自 yijiu.blo g.51 cto.com
[root@node1 tools]# pt-table-sync --replicate=testdb.checksums --databases=test110 h=10.12.33.58,u=root,p=mypass --execute
[root@node1 tools]# echo $?
0
[root@node1 tools]# pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=testdb.checksums --create-replicate-table --databases=test110 -h 10.12.33.58 -P 3306 -u root -p mypass --recursion-method="processlist"
TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE
11-12T16:49:12 0 0 1011 1 0 0.068 test110.yw
案例
好比一個很大的庫,白天發生數據的不一致,嘗試着手動修復,好比1062 1032等
可是1032的數據很是的多,這個時間從庫一方面能夠下線並重作
(1062,1032 可使用slave_skip_errors=all 方式,而後用check-sum 進行修復)
另外一種方法將從庫不提供服務,並執行順序:
slave_skip_errors = all #將全部的錯誤都跳過,讓從庫繼續工做
pt-table-checksum #在業務低峯期的時候執行,對出現錯誤的表進行檢查並嘗試修復
pt-table-sync #把不一致的數據補上來
#將slave_skip_errors = all關閉
check-sum #惟一的不足是將數據所有讀完,會將buffer pool熱數據沖掉
盜貼麻煩 說一w聲,本 文來自 yijiu.blog.51 cto.com
模擬場景
從庫執行
mysql> call insert_yw(1);
主庫操做
mysql> call insert_yw(1);
Query OK, 1 row affected (0.01 sec)
再次查看從庫
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.12.33.58
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 573305
Relay_Log_File: node2-relay-bin.000003
Relay_Log_Pos: 564426
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1062
Last_Error: Could not execute Write_rows event on table test110.yw; Duplicate entry '1013' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000002, end_log_pos 572982
Skip_Counter: 0
若是線程不工做的話 pt-table-checksum是沒法檢測的,因此要將線程啓動
盜貼麻煩 說一a聲,本 文來自 yijiu.blog.51 cto.com
將全部錯誤跳過
[root@node2 mysql]# grep errors /etc/my.cnf
slave_skip_errors = all
並重啓服務
使用pt-table-checksum檢測
[root@node1 tools]# pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=testdb.checksums --create-replicate-table --databases=test110 -h node1.test.com -P 3306 -u root -p mypass --recursion-method="processlist"
TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE
11-12T17:19:33 0 1 1015 1 0 0.033 test110.yw
進行修復
[root@node1 tools]# pt-table-sync --replicate=testdb.checksums --databases=test110 h=10.12.33.58,u=root,p=mypass --execute
[root@node1 tools]# echo $?
0
在雙方都確認行數
mysql> select count(*) from yw;
+----------+
| count(*) |
+----------+
| 1015 |
+----------+
1 row in set (0.00 sec)
面試中會問到tp-check-sum的不足:
1.會將全部數據從新讀一遍
2.讀數據的同時會將buffer池中的熱數據沖掉
3.在主庫有大量的讀,可是不會鎖表是個很是不錯的功能
若是是庫很是小的話,或者幾百G的數據,直接將重建主從便可
若是全庫修復的話,量大的話則須要五、6個小時,具體須要機器配置
盜貼麻煩 說一a聲,本文來自 yijiu.blog.51 cto.com
pt-table-checksum的工做過程
在主庫將general log 將主從都打開並運行pt-table-checksum進行觀察
mysql> set global general_log=1;
Query OK, 0 rows affected (0.00 sec)
mysql> show global variables like '%gen%';
+------------------+------------------------+
| Variable_name | Value |
+------------------+------------------------+
| general_log | ON |
| general_log_file | /mydata/data/node2.log |
+------------------+------------------------+
2 rows in set (0.00 sec)
Pt-table-checksum的工做流程:
在某些數據不超過1千行則馬上顯示出;若是超過1千行,會進行分段,至於如何分段其內部有特定機制
開啓general log後在主庫執行tp-table-checksum
[root@node1 ~]# pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=testdb.checksums --create-replicate-table --databases=test110 -h node1.test.com -P 3306 -u root -p mypass --recursion-method="processlist"
TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE
11-13T16:25:47 0 0 1015 1 0 0.048 test110.yw
主庫:
[root@node1 ~]# cat /mydata/data/node1.log
141113 16:25:47 63 Connect root@node1.test.com on
63 Queryset autocommit=1
63 QuerySELECT @@SQL_MODE
63 QuerySHOW VARIABLES LIKE 'innodb\_lock_wait_timeout'
63 QuerySET SESSION innodb_lock_wait_timeout=1
63 QuerySHOW VARIABLES LIKE 'wait\_timeout'
63 QuerySET SESSION wait_timeout=10000
63 QuerySET @@SQL_QUOTE_SHOW_CREATE = 1/*!40101, @@SQL_MODE='NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'*/
63 QuerySELECT @@server_id /*!50038 , @@hostname*/
63 QuerySHOW VARIABLES LIKE 'version%'
63 QuerySHOW ENGINES
63 QuerySHOW VARIABLES LIKE 'innodb_version'
63 QuerySELECT @@binlog_format
#生成表後將session 會話級別的binlog格式改成語句級別格式
63 Query/*!50108 SET @@binlog_format := 'STATEMENT'*/ #更改日誌格式爲STAEMENT
63 QuerySET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
63 QuerySHOW VARIABLES LIKE 'wsrep_on'
63 QuerySELECT @@SERVER_ID
63 QuerySHOW GRANTS FOR CURRENT_USER()
63 QuerySHOW PROCESSLIST
63 QuerySELECT @@server_id
63 QuerySELECT @@server_id
63 QuerySHOW DATABASES LIKE 'testdb'
63 QueryCREATE DATABASE IF NOT EXISTS `testdb` /* pt-table-checksum */
63 QueryUSE `testdb`
63 QuerySHOW TABLES FROM `testdb` LIKE 'checksums'
#通過上面一系列檢測、建立庫、進入庫,接下來建立checksums表
63 QueryCREATE TABLE IF NOT EXISTS `testdb`.`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
63 QuerySHOW GLOBAL STATUS LIKE 'Threads_running'
63 QuerySELECT CONCAT(@@hostname, @@port) #檢測主機名
63 QuerySELECT CRC32('test-string')
63 QuerySELECT CRC32('a')
63 QuerySELECT CRC32('a')
63 QuerySHOW VARIABLES LIKE 'wsrep_on'
63 QuerySHOW DATABASES
63 QuerySHOW /*!50002 FULL*/ TABLES FROM `test110`
63 Query/*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, @@SQL_MODE := '', @OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, @@SQL_QUOTE_SHOW_CREATE := 1 */
63 QueryUSE `test110`
63 QuerySHOW CREATE TABLE `test110`.`yw`
63 Query/*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, @@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */
63 QueryEXPLAIN SELECT * FROM `test110`.`yw` WHERE 1=1
63 QueryUSE `testdb`
63 QueryDELETE FROM `testdb`.`checksums` WHERE db = 'test110' AND tbl = 'yw'
63 QueryUSE `test110`
#然後對每張表進行如下語句
63 QueryEXPLAIN SELECT COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `id`, `c1`, `c2`, `c3`, `c4`, `c5` + 0, `c6`)) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `test110`.`yw` /*explain checksum table*/
#後執行如下函數,主要是將一個列拼成了一個用#號隔開的字符串
63 QueryREPLACE INTO `testdb`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT 'test110', 'yw', '1', NULL, NULL, NULL, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `id`, `c1`, `c2`, `c3`, `c4`, `c5` + 0, `c6`)) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `test110`.`yw` /*checksum table*/
63 QuerySHOW WARNINGS
63 QuerySELECT this_crc, this_cnt FROM `testdb`.`checksums` WHERE db = 'test110' AND tbl = 'yw' AND chunk = '1'
63 QueryUPDATE `testdb`.`checksums` SET chunk_time = '0.008188', master_crc = 'dea4b11d', master_cnt = '1015' WHERE db = 'test110' AND tbl = 'yw' AND chunk = '1'
63 QuerySHOW GLOBAL STATUS LIKE 'Threads_running'
63 Quit
將語句所有寫到checksums表中,這樣若是主庫執行了crc32函數的話,那麼從庫再執這些列進行crc32函數相匹配,若是值不同的話,則數據不一致
由於語句級的複製,只是將語句傳遞到不一樣的庫去執行,這樣的話無論有多少個從庫都會將在主庫將此語句跑完然後在從庫上也執行此條語句並在從庫執行
執行完後將語句所有寫chechksums中,然後經過pt-table-checksum去讀這個表,是否跟主庫的crc32去對比,若是不同則認爲數據是不正確的,並且會分段列出,然後嘗試修復
pt-table-checksum修復的過程
依舊將語句改成行格式,然後在主庫執行replace into,其做用是主要修復主庫上存在的語句,而從庫沒有的數據,或者主從都有主鍵,可是從庫和主庫的數據有衝突
另一種是從庫存在數據,而主庫沒有數據,則在主庫執行delete操做,然後將語句記錄在binlog中,再將binlog同步到relay log使從庫上刪掉
模擬錯誤
從庫執行
mysql> set global sql_slave_skip_counter = 1;
Query OK, 0 rows affected (0.00 sec)
mysql> call insert_yw(1);
Query OK, 1 row affected (0.00 sec)
mysql> select count(*) from yw;
+----------+
| count(*) |
+----------+
| 1016 |
+----------+
1 row in set (0.00 sec)
主庫執行
mysql> use test110;
Database changed
mysql> call insert_yw(2);
Query OK, 1 row affected (0.02 sec)
mysql> select count(*) from yw;
+----------+
| count(*) |
+----------+
| 1017 |
+----------+
1 row in set (0.00 sec)
嘗試在主庫修復不一致
[root@node1 ~]# pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=testdb.checksums --create-replicate-table --databases=test110 -h node1.test.com -P 3306 -u root -p mypass --recursion-method="processlist"
# 2 software updates are available:
# * The current version for MySQL Community Server (GPL) is 5.6.21.
# * The current version for MySQL Community Server (GPL) is 5.6.21.
TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE
11-13T17:03:57 0 1 1017 1 0 0.070 test110.yw
觀察general log
[root@node1 ~]# cat /mydata/data/node1.log
141113 17:07:45 67 Connect root@node1.test.com on
67 Queryset autocommit=0
67 QuerySELECT @@SQL_MODE
67 QuerySHOW VARIABLES LIKE 'wait\_timeout'
67 QuerySET SESSION wait_timeout=10000
67 QuerySET @@SQL_QUOTE_SHOW_CREATE = 1/*!40101, @@SQL_MODE='NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'*/
67 Query/*!40101 SET @@SQL_MODE := CONCAT(@@SQL_MODE, ',NO_AUTO_VALUE_ON_ZERO')*/
67 QuerySHOW VARIABLES LIKE 'version%'
67 QuerySHOW ENGINES
67 QuerySHOW VARIABLES LIKE 'innodb_version'
67 QuerySELECT @@binlog_format
67 Query/*!50108 SET @@binlog_format := 'STATEMENT'*/ #依舊將語句改成行格式,然後在主庫執行replace into
67 QuerySET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
67 QuerySELECT CONCAT(@@hostname, @@port)
67 Quit
68 Connect root@node1.test.com on
68 Queryset autocommit=0
68 QuerySELECT @@SQL_MODE
68 QuerySHOW VARIABLES LIKE 'wait\_timeout'
68 QuerySET SESSION wait_timeout=10000
68 QuerySET @@SQL_QUOTE_SHOW_CREATE = 1/*!40101, @@SQL_MODE='NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'*/
68 Query/*!40101 SET @@SQL_MODE := CONCAT(@@SQL_MODE, ',NO_AUTO_VALUE_ON_ZERO')*/
68 QuerySHOW VARIABLES LIKE 'version%'
68 QuerySHOW ENGINES
68 QuerySHOW VARIABLES LIKE 'innodb_version'
68 QuerySELECT @@binlog_format
68 Query/*!50108 SET @@binlog_format := 'STATEMENT'*/
68 QuerySET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
69 Connect root@node1.test.com on
69 Queryset autocommit=0
69 QuerySELECT @@SQL_MODE
69 QuerySHOW VARIABLES LIKE 'wait\_timeout'
69 QuerySET SESSION wait_timeout=10000
69 QuerySET @@SQL_QUOTE_SHOW_CREATE = 1/*!40101, @@SQL_MODE='NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'*/
69 Query/*!40101 SET @@SQL_MODE := CONCAT(@@SQL_MODE, ',NO_AUTO_VALUE_ON_ZERO')*/
69 QuerySHOW VARIABLES LIKE 'version%'
69 QuerySHOW ENGINES
69 QuerySHOW VARIABLES LIKE 'innodb_version'
69 QuerySELECT @@binlog_format
69 Query/*!50108 SET @@binlog_format := 'STATEMENT'*/
69 QuerySET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
68 QuerySELECT @@SERVER_ID
68 QuerySELECT db, tbl, CONCAT(db, '.', tbl) AS `table`, chunk, chunk_index, lower_boundary, upper_boundary, COALESCE(this_cnt-master_cnt, 0) AS cnt_diff, COALESCE(this_crc <> master_crc OR ISNULL(master_crc) <> ISNULL(this_crc), 0) AS crc_diff, this_cnt, master_cnt, this_crc, master_crc FROM testdb.checksums WHERE master_cnt <> this_cnt OR master_crc <> this_crc OR ISNULL(master_crc) <> ISNULL(this_crc)
68 QuerySHOW GRANTS FOR CURRENT_USER()
68 QuerySHOW PROCESSLIST
68 Query/*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, @@SQL_MODE := '', @OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, @@SQL_QUOTE_SHOW_CREATE := 1 */
68 QueryUSE `test110`
68 QuerySHOW CREATE TABLE `test110`.`yw`
68 Query/*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, @@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */
68 QuerySELECT table_schema, table_name FROM information_schema.key_column_usage WHERE constraint_schema='test110' AND referenced_table_name='yw'
68 QuerySELECT MIN(`id`), MAX(`id`) FROM `test110`.`yw` FORCE INDEX (`PRIMARY`)
68 QueryEXPLAIN SELECT * FROM `test110`.`yw` FORCE INDEX (`PRIMARY`)
68 QuerySELECT CRC32('test-string')
68 QuerySELECT CRC32('a')
68 QuerySELECT CRC32('a')
68 QueryUSE `test110`
68 QuerySET @crc := '', @cnt := 0
68 Querycommit
68 QuerySTART TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */
68 QuerySELECT /*test110.yw:1/3*/ 0 AS chunk_num, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `id`, `c1`, `c2`, `c3`, `c4`, `c5` + 0, `c6`)) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `test110`.`yw` FORCE INDEX (`PRIMARY`) WHERE (`id` = 0) FOR UPDATE
69 QuerySHOW MASTER STATUS
68 QuerySET @crc := '', @cnt := 0
68 Querycommit
68 QuerySTART TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */
68 QuerySELECT /*test110.yw:2/3*/ 1 AS chunk_num, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `id`, `c1`, `c2`, `c3`, `c4`, `c5` + 0, `c6`)) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `test110`.`yw` FORCE INDEX (`PRIMARY`) WHERE (`id` > 0 AND `id` < '1001') FOR UPDATE
69 QuerySHOW MASTER STATUS
68 QuerySET @crc := '', @cnt := 0
68 Querycommit
68 QuerySTART TRANSACTION /*!40108 WITH CONSISTENT SNAPSHOT */
68 QuerySELECT /*test110.yw:3/3*/ 2 AS chunk_num, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `id`, `c1`, `c2`, `c3`, `c4`, `c5` + 0, `c6`)) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `test110`.`yw` FORCE INDEX (`PRIMARY`) WHERE (`id` >= '1001') FOR UPDATE
69 QuerySHOW MASTER STATUS
68 QuerySET @crc := '', @cnt := 0
68 QuerySELECT /*rows in chunk*/ `id`, `c1`, `c2`, `c3`, `c4`, `c5` + 0 AS `c5`, `c6`, CRC32(CONCAT_WS('#', `id`, `c1`, `c2`, `c3`, `c4`, `c5` + 0, `c6`)) AS __crc FROM `test110`.`yw` FORCE INDEX (`PRIMARY`) WHERE (`id` >= '1001') ORDER BY `id` FOR UPDATE
68 QuerySELECT `id`, `c1`, `c2`, `c3`, `c4`, `c5`, `c6` FROM `test110`.`yw` WHERE `id`='1016' LIMIT 1
#然後在主庫執行replace into,其做用是主要修復主庫上存在的語句,而從庫沒有的數據,或者主從都有主鍵,可是從庫和主庫的數據有衝突
#另一種是從庫存在數據,而主庫沒有數據,則在主庫執行delete操做,然後將語句記錄在binlog中,再將binlog同步到relay log使從庫上刪掉
68 QueryREPLACE INTO `test110`.`yw`(`id`, `c1`, `c2`, `c3`, `c4`, `c5`, `c6`) VALUES ('1016', '1', '1', '1', '1', '2014-11-13 17:02:24', 'testdbtestdbtestdb') /*percona-toolkit src_db:test110 src_tbl:yw src_dsn:h=10.12.33.58,p=...,u=root dst_db:test110 dst_tbl:yw dst_dsn:h=node2.test.com,p=...,u=root lock:1 transaction:1 changing_src:testdb.checksums replicate:testdb.checksums bidirectional:0 pid:15761 user:root host:node1.test.com*/
68 QuerySELECT `id`, `c1`, `c2`, `c3`, `c4`, `c5`, `c6` FROM `test110`.`yw` WHERE `id`='1017' LIMIT 1
68 QueryREPLACE INTO `test110`.`yw`(`id`, `c1`, `c2`, `c3`, `c4`, `c5`, `c6`) VALUES ('1017', '1', '0', '1', '0', '2014-11-13 17:02:24', 'testdbtestdbtestdbtestdbtestdbtestdbtestdbtestdbtestdbtestdbtestdbtestdbtestdbtestdbtestdb') /*percona-toolkit src_db:test110 src_tbl:yw src_dsn:h=10.12.33.58,p=...,u=root dst_db:test110 dst_tbl:yw dst_dsn:h=node2.test.com,p=...,u=root lock:1 transaction:1 changing_src:testdb.checksums replicate:testdb.checksums bidirectional:0 pid:15761 user:root host:node1.test.com*/
68 Querycommit
68 Querycommit
68 Quit
69 Querycommit
69 Quit
依舊將語句改成行格式,然後在主庫執行replace into,其做用是主要修復主庫上存在的語句,而從庫沒有的數據,或者主從都有主鍵,可是從庫和主庫的數據有衝突
另一種是從庫存在數據,而主庫沒有數據,則在主庫執行delete操做,然後將語句記錄在binlog中,再將binlog同步到relay log使從庫上刪掉
修復完畢後再次檢測
[root@node1 ~]# pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=testdb.checksums --create-replicate-table --databases=test110 -h node1.test.com -P 3306 -u root -p mypass --recursion-method="processlist"
TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE
11-13T17:13:45 0 0 1017 1 0 0.075 test110.yw