MySQL複製

複製容許未來自一個MySQL數據庫服務器(主服務器)的數據複製到一個或多個MySQL數據庫服務器(從服務器)。 默認狀況下,複製是異步的。 根據配置,您能夠複製數據庫中的全部數據庫,所選數據庫甚至選定的表。html

1. 複製的原理

replication的工做原理分爲如下3個步驟:java

  • 1)主服務器(master)把數據更改記錄到二進制日誌(binlog)中。python

  • 2)從服務器(slave)的I/O thread請求主服務器binlog,主服務器經過I/O dump thread傳送binlog日誌到從服務器的I/O thread,而後I/O thread把日誌寫入到中繼日誌(relay log)中。mysql

  • 3)從服務器經過SQL thread重作中繼日誌中的日誌,把更改應用到本身的數據庫上,以達到數據庫的最終一致性。web

2. 複製的重點參數

  • log-bin
    搭建主從複製,必須開啓二進制日誌sql

  • server_id
    MySQL在同一組主從結構中的惟一標識(主從服務器上該參數不能一致)數據庫

  • server_uuid
    在MySQL 5.7中,除了用戶提供的–server-id以外,服務器還生成一個真正的UUID。這可用做全局只讀變量server_uuid。
    啓動時,MySQL服務器自動獲取UUID,以下所示:安全

    • 嘗試讀取和使用文件data_dir/auto.cnf中編寫的UUID(其中data_dir是服務器的數據目錄)。
    • 若是找不到data_dir/auto.cnf,則生成新的UUID並將其保存到此文件,必要時建立該文件。
  • read_only
    啓用read_only系統變量後,除具備SUPER權限的用戶外,服務器不容許客戶端更新。默認狀況下禁用此變量。
    服務器還支持super_read_only系統變量(默認狀況下禁用),它具備如下做用:bash

    • 若是啓用了super_read_only,則服務器禁止客戶端更新,即便是具備SUPER權限的用戶也是如此。
    • 將super_read_only設置爲ON會隱式強制read_only爲ON。
    • 將read_only設置爲OFF會隱式強制將super_read_only強制爲OFF。
  • binlog_format
    二進制日誌的格式,必須使用row模式服務器

  • log_slave_updates
    從服務器是否應將其SQL線程執行的更新記錄到其本身的二進制日誌中。

  • binlog_error_action
    控制服務器沒法寫入二進制日誌時發生的狀況
    在MySQL5.7.7後,默認值爲ABORT_SERVER,以前版本默認值爲IGNORE_ERROR

    • ABORT_SERVER:服務器在遇到二進制日誌的此類錯誤時中止日誌記錄並關閉。 在服務器從新啓動時,將提交全部先前準備的和二進制記錄的事務,同時停止因爲錯誤而準備但未進行二進制記錄的任何事務。
    • IGNORE_ERROR:服務器遇到以上錯誤時,MySQL會在錯誤日誌中記錄錯誤,並強制關閉binlog功能。
  • binlog-do-db
    使用該參數可選擇性複製數據庫,如binlog-do-db=test,表示只複製test庫。

  • binlog-ignore-db
    該參數是忽略某個庫的複製。如binlog-ignore-db=test,表示除了test庫,其餘庫都複製。

  • gtid_mode
    控制是否啓用基於GTID的日誌記錄以及日誌能夠包含的事務類型

    • ON:新的和複製的事務都必須是GTID事務。
    • ON_PERMISSIVE:新事務是GTID事務,複製事務能夠是GTID也能夠不是GTID事務
    • OFF_PERMISSIVE:新事務不是GTID事務,複製事務能夠是GTID也能夠不是GTID事務
    • OFF:不產生GTID,只接受不帶GTID的事務
  • enforce_gtid_consistency
    啓用後,服務器經過容許僅執行可以使用GTID安全記錄的語句來強制執行GTID一致性。在啓用基於GTID的複製以前,必須將此選項設置爲ON。
    能夠配置–enforce-gtid-consistency的值爲:

    • OFF:容許全部事務違反GTID一致性。
    • ON:不容許任何事務違反GTID一致性。
    • WARN:容許全部事務違反GTID一致性,但在這種狀況下會生成警告。在MySQL 5.7.6中添加了WARN。
  • gtid_next
    指定要執行的下一個語句的GTID.
    gtid_next能夠採用如下任何值:

    • AUTOMATIC: 默認值,使用下一個自動生成的全局事務ID。
    • ANONYMOUS:事務沒有全局標識符,僅由文件和位置標識。
    • UUID:NUMBER格式的全局事務ID。
  • gtid_purged
    從二進制日誌中清除的全部GTID的集合

  • gtid_executed_compression_period
    每處理多少次事務時,壓縮mysql.gtid_executed表。 設置爲0表示此表未壓縮。默認值1000

  • gtid_owned
    此只讀變量包含一個列表,其內容取決於其範圍。當與會話範圍一塊兒使用時,該列表包含此客戶端擁有的全部GTID;當與全局範圍一塊兒使用時,它包含全部GTID及其全部者的列表。

  • relay_log
    記錄從庫I/O thread從主庫讀取來的binlog內容

  • relay_log_info_repository
    應用二進制日誌中的內容,並將binlog應用到的位置記錄到relay.info文件中,建議使用表記錄(mysql.slave_relay_log_info)

  • master_info_repository
    把master.info(主從狀態,配置信息)記錄下來,默認記錄到file裏,建議使用表記錄(mysql.slave_master_info)。

  • relay_log_purge
    禁用或啓用自動清除中繼日誌文件。默認值爲1(ON)。

  • relay_log_recovery
    爲了讓從庫是crash safe的,必須設置relay_log_recovery=1。該參數的含義是:當從庫發生崩潰或者重啓時,它會把那些未執行完的中繼日誌刪除,並會向主庫從新獲取binlog,再次生成relay log來完成恢復。建議開啓,默認是關閉狀態。

  • REPLICATE_DO_DB=name
    CHANGE REPLICATION FILTER Syntax
    只複製指定的庫,在從庫上使用。 至關於--replicate-do-db

  • REPLICATE_IGNORE_DB
    在複製中,排除指定的庫,在從庫上使用。 至關於--replicate-ignore-db

  • REPLICATE_DO_TABLE
    只複製指定的表,在從庫上使用。至關於--replicate-do-table

  • REPLICATE_IGNORE_TABLE
    排除指定的表,在從庫上使用。至關於--replicate-ignore-table

  • REPLICATE_WILD_DO_TABLE
    使用通配符複製指定的表。如
    CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = ('db1.old%');複製db1庫中,old開頭的表。 至關於--replicate-wild-do-table

  • REPLICATE_WILD_IGNORE_TABLE
    在複製中,排除通配符的的表,如CHANGE REPLICATION FILTER REPLICATE_WILD_IGNORE_TABLE = ('db1.new%', 'db2.new%');,排除new開頭的表。 至關於--replicate-wild-ignore-table

  • REPLICATE_REWRITE_DB
    在從服務器上替換主服務器上指定數據庫的新名稱後,對從服務器執行更新。至關於--replicate-rewrite-db=from_name->to_name

  • slave_net_timeout
    該參數是設置在多少秒沒收到主庫傳來的binlog以後,從庫認爲是網絡超時,從庫的I/O thread會從新鏈接主庫。從MySQL5.7.7後默認值爲60s,之前版本默認值爲3600s

  • slave_parallel_type
    從庫使用多線程(slave_parallel_workers大於0)時,此變量指定用於決定容許哪些事務在slave上並行執行的策略。該變量對未啓用多線程的slave沒有影響。

  • LOGICAL_CLOCK:做爲主服務器上相同二進制日誌組提交的一部分的事務在從服務器上並行應用。根據事務的時間戳跟蹤事務之間的依賴關係,以便在可能的狀況下提供額外的並行化。設置此值後,能夠在主服務器上使用binlog_transaction_dependency_tracking系統變量,以指定寫入集用於並行化而不是時間戳,若是寫入集可用於事務而且與時間戳相比提供改進的結果。

  • DATABASE:更新不一樣數據庫的事務並行應用。僅當數據被分區爲多個數據庫時才適用此值,這些數據庫在主服務器上獨立並同時更新。必須沒有跨數據庫約束,由於可能會在從屬設備上違反這些約束。

  • slave_parallel_workers
    設置多個線程來併發執行relay log中主庫提交的事務,最大值爲1024.

3. 傳統複製搭建(非GTID模式)

非GTID模式複製,基於binlog和position方式來搭建複製。

3.1 環境準備

類型 ip prot server-id 是否開啓binlog binlog格式 log_slave_updates參數
master 192.168.56.100 3306 1003306 log-bin = /data/mysql/mysql3306/logs/my3306_binlog binlog_format = row log_slave_updates=1
slave 192.168.56.200 3306 2003306 log-bin = /data/mysql/mysql3306/logs/my3306_binlog binlog_format = row log_slave_updates=1

從庫開啓binlog,而且開啓log_slave_updates參數,讓從庫也寫binlog,方便後期擴展。

3.2 在master上操做

1) 建立複製帳號

create user 'repl'@'%' identified by 'wanbin'; grant replication slave on *.* to 'repl'@'%'; create user 'repl'@'%' identified by 'wanbin'; grant replication slave on *.* to 'repl'@'%';

2) master數據庫利用xtrabackup備份至slave上

innobackupex --defaults-file=/etc/my3306.cnf -ubackup -pmysql --stream=tar ./ |ssh root@mysqldb2 "cat - > /data/backup/dbback`date +%Y%m%d_%H%M%S`.tar"

3.3 在slave上操做

  1. 解壓
mkdir dbback20180918_163934

tar -xvf dbback20180918_163934.tar -C dbback20180918_163934
  1. prepare 備份
innobackupex --apply-log /data/backup/dbback20180918_163934/
  1. 恢復備份
cd /data/mysql/mysql3306/

mv data data_bak

mkdir data

innobackupex --defaults-file=/etc/my.cnf --copy-back /data/backup/dbback20180918_163934/

chown -R mysql:mysql /data/mysql/mysql3306/data

mysqld --defaults-file=/etc/my.cnf &
  1. 配置主從
cd /data/mysql/mysql3306/data

# cat xtrabackup_info
uuid = ff24a119-bb1e-11e8-b580-080027b0b461
name = 
tool_name = innobackupex
tool_command = --defaults-file=/etc/my3306.cnf -ubackup -pmysql --stream=tar ./
tool_version = 2.4.12
ibbackup_version = 2.4.12
server_version = 5.7.23-log
start_time = 2018-09-18 16:39:35
end_time = 2018-09-18 16:44:03
lock_time = 0
binlog_pos = filename 'my3306_binlog.000069', position '635'
innodb_from_lsn = 0
innodb_to_lsn = 4105428323
partial = N
incremental = N
format = tar
compact = N
compressed = N
encrypted = N


執行help change master to 能夠獲取change master to命令

CHANGE MASTER TO
  MASTER_HOST='192.168.56.100',
  MASTER_USER='repl',
  MASTER_PASSWORD='wanbin',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='my3306_binlog.000069',
  MASTER_LOG_POS=635;
  1. 開始主從複製
start slave; #若是想分別指定啓動線程,可使用以下命令 START SLAVE IO_THREAD; START SLAVE SQL_THREAD; #一樣關閉命令: STOP SLAVE; #分別關閉命令: STOP SLAVE IO_THREAD; STOP SLAVE SQL_THREAD; start slave; #若是想分別指定啓動線程,可使用以下命令 START SLAVE IO_THREAD; START SLAVE SQL_THREAD; #一樣關閉命令: STOP SLAVE; #分別關閉命令: STOP SLAVE IO_THREAD; STOP SLAVE SQL_THREAD;
  1. 查看主從複製狀態
show slave status\G ... Slave_IO_Running: Yes Slave_SQL_Running: No ... Last_Error: Error 'Operation CREATE USER failed for 'repl'@'%'' on query. Default database: ''. Query: 'CREATE USER 'repl'@'%' IDENTIFIED WITH 'mysql_native_password' AS '*F9E8175DA937ECCE88EE1CF18505FBDB049417E1'' #SQL thread線程沒有起來,並報相應的錯誤。 #後經查看,是change master命令,指定的位置不對,致使的錯誤。 #錯誤解決: stop slave; reset slave all; CHANGE MASTER TO MASTER_HOST='192.168.56.100', MASTER_USER='repl', MASTER_PASSWORD='wanbin', MASTER_PORT=3306, MASTER_LOG_FILE='my3306_binlog.000069', MASTER_LOG_POS=635; start slave; 查看狀態 show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.56.100 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: my3306_binlog.000069 Read_Master_Log_Pos: 787 Relay_Log_File: mysqldb2-relay-bin.000002 Relay_Log_Pos: 476 Relay_Master_Log_File: my3306_binlog.000069 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 787 Relay_Log_Space: 686 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1003306 Master_UUID: 7390a401-b705-11e8-9ed9-080027b0b461 Master_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: 17c50389-9537-11e8-a44c-08002712513f:1-2, b019ea48-b729-11e8-99cb-08002712513f:1, e4382832-949d-11e8-97ba-080027793430:1-154 Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: show slave status\G ... Slave_IO_Running: Yes Slave_SQL_Running: No ... Last_Error: Error 'Operation CREATE USER failed for 'repl'@'%'' on query. Default database: ''. Query: 'CREATE USER 'repl'@'%' IDENTIFIED WITH 'mysql_native_password' AS '*F9E8175DA937ECCE88EE1CF18505FBDB049417E1'' #SQL thread線程沒有起來,並報相應的錯誤。 #後經查看,是change master命令,指定的位置不對,致使的錯誤。 #錯誤解決: stop slave; reset slave all; CHANGE MASTER TO MASTER_HOST='192.168.56.100', MASTER_USER='repl', MASTER_PASSWORD='wanbin', MASTER_PORT=3306, MASTER_LOG_FILE='my3306_binlog.000069', MASTER_LOG_POS=635; start slave; 查看狀態 show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.56.100 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: my3306_binlog.000069 Read_Master_Log_Pos: 787 Relay_Log_File: mysqldb2-relay-bin.000002 Relay_Log_Pos: 476 Relay_Master_Log_File: my3306_binlog.000069 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 787 Relay_Log_Space: 686 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1003306 Master_UUID: 7390a401-b705-11e8-9ed9-080027b0b461 Master_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: 17c50389-9537-11e8-a44c-08002712513f:1-2, b019ea48-b729-11e8-99cb-08002712513f:1, e4382832-949d-11e8-97ba-080027793430:1-154 Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version:
  1. SHOW SLAVE STATUS的主要變量
變量 說明
Slave_IO_State 顯示當前IO線程的狀態,上述狀態顯示的是等待主服務發送二進制日誌
Master_Log_File 顯示當前同步的主服務器的binlog,上述顯示當前同步的是主服務器的my3306_binlog.000071
Read_Master_Log_Pos 顯示當前同步到主服務器上二進制日誌的偏移量位置,單位是字節。
Relay_Master_Log_File 當前中繼日誌同步的二進制日誌
Relay_Log_File 顯示當前寫入的中繼日誌
Relay_Log_Pos 顯示當前寫入中繼日誌的偏移量位置
Slave_IO_Running 從服務器IO線程運行狀態。YES表示正常
Slave_SQL_Running 從服務器SQL線程運行狀態。YES表示正常
Exec_Master_Log_Pos 表示同步到主服務器的二進制日誌偏移量位置。

查看SQL線程延遲的方法:

Master_Log_File = Relay_Master_Log_File 而且 Read_Master_Log_Pos - Exec_Master_Log_Pos = 0

#表示沒有延遲

查看IO線程延遲的方法:
在主服務器上查看二進制狀態,如:

> SHOW master status\G *************************** 1. row *************************** File: my3306_binlog.000071 Position: 386 Binlog_Do_DB: Binlog_Ignore_DB: Executed_Gtid_Set: e4382832-949d-11e8-97ba-080027793430:1-154 1 row in set (0.00 sec) #用Position 減去從服務器上 Master_Log_File 值,就可得知IO線程的延時。上述沒有延時。 > SHOW master status\G *************************** 1. row *************************** File: my3306_binlog.000071 Position: 386 Binlog_Do_DB: Binlog_Ignore_DB: Executed_Gtid_Set: e4382832-949d-11e8-97ba-080027793430:1-154 1 row in set (0.00 sec) #用Position 減去從服務器上 Master_Log_File 值,就可得知IO線程的延時。上述沒有延時。

4. 主從複製故障處理

  • 從庫上出現寫入數據,把自增id佔用:1062錯誤

  • 從庫上出現少數據,delete,update操做時,找不到相應記錄。錯誤號:1032

4.1 錯誤號1062處理

模擬故障

 #1. 在master上建立表 create table z1(id int not null,uname varchar(32),primary key(id)); #2. 在slave上插入數據 set sql_log_bin=0; set global read_only=off; insert into z1(id,uname) values(3,'python'); #3. 在master上插入數據 insert into z1(id,uname) values(2,'mysql'); insert into z1(id,uname) values(3,'java'); #1. 在master上建立表 create table z1(id int not null,uname varchar(32),primary key(id)); #2. 在slave上插入數據 set sql_log_bin=0; set global read_only=off; insert into z1(id,uname) values(3,'python'); #3. 在master上插入數據 insert into z1(id,uname) values(2,'mysql'); insert into z1(id,uname) values(3,'java');

查看slave status

>show slave status\G ... Slave_IO_Running: Yes Slave_SQL_Running: No ... Last_SQL_Errno: 1062 Last_SQL_Error: Could not execute Write_rows event on table test.z1; Duplicate entry '3' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log my3306_binlog.000071, end_log_pos 1214 >show slave status\G ... Slave_IO_Running: Yes Slave_SQL_Running: No ... Last_SQL_Errno: 1062 Last_SQL_Error: Could not execute Write_rows event on table test.z1; Duplicate entry '3' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log my3306_binlog.000071, end_log_pos 1214

修復錯誤

  1. 利用pt-slave-restart 工具跳過此錯誤。
pt-slave-restart --error-numbers=1062 2018-09-19T15:24:02 mysqldb2-relay-bin.000019 1088 1062 #查看slave staus ··· Slave_IO_Running: Yes Slave_SQL_Running: Yes ··· #說明覆制已經正常,跳過了錯誤事務。 #可是master與slave上的這張表數據不一致,因此這種修復方法只能算暫時的。 #以後還需進行修復 pt-slave-restart --error-numbers=1062 2018-09-19T15:24:02 mysqldb2-relay-bin.000019 1088 1062 #查看slave staus ··· Slave_IO_Running: Yes Slave_SQL_Running: Yes ··· #說明覆制已經正常,跳過了錯誤事務。 #可是master與slave上的這張表數據不一致,因此這種修復方法只能算暫時的。 #以後還需進行修復
  1. 經過pt-table-checksum工具查找數據不一致的表
pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=test.checksums --create-replicate-table --databases=test --tables=z1 h=192.168.56.100,u=wanbin,p=mysql,P=3306


#經常使用參數解釋:
--nocheck-replication-filters :不檢查複製過濾器,建議啓用。後面能夠用--databases來指定須要檢查的數據庫。
--no-check-binlog-format : 不檢查複製的binlog模式,要是binlog模式是ROW,則會報錯。
--replicate-check-only :只顯示不一樣步的信息。
--replicate= :把checksum的信息寫入到指定表中,建議直接寫到被檢查的數據庫當中。
--databases= :指定須要被檢查的數據庫,多個則用逗號隔開。
--tables= :指定須要被檢查的表,多個用逗號隔開
h= :Master的地址
u= :用戶名
p=:密碼
P= :端口

Checking if all tables can be checksummed ...
Starting checksum ...
            TS ERRORS  DIFFS     ROWS  DIFF_ROWS  CHUNKS SKIPPED    TIME TABLE
09-19T15:58:29      0      1        2          0       1       0   0.086 test.z1

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

pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=test.checksums --create-replicate-table --databases=test --replicate-check-only  h=192.168.56.100,u=wanbin,p=mysql,P=3306

Checking if all tables can be checksummed ...
Starting checksum ...
Differences on mysqldb2
TABLE CHUNK CNT_DIFF CRC_DIFF CHUNK_INDEX LOWER_BOUNDARY UPPER_BOUNDARY
test.z1 1 -1 1   


【注意】:
1)根據測試,須要一個即能登陸主庫,也能登陸從庫的帳號;
2)只能指定一個host,必須爲主庫的IP;
3)在檢查時會向表加S鎖;
4)運行以前須要從庫的同步IO和SQL進程是YES狀態。
  1. 使用pt-table-sync修復數據

pt-table-sync: 高效的同步MySQL表之間的數據,他能夠作單向和雙向同步的表數據。他能夠同步單個表,也能夠同步整個庫。它不一樣步表結構、索引、或任何其餘模式對象。因此在修復一致性以前須要保證他們表存在。

#print修復命令

pt-table-sync --replicate=test.checksums h=192.168.56.100,u=wanbin,p=mysql,P=3306 h=192.168.56.200,u=wanbin,p=mysql,P=3306 --print

REPLACE INTO `test`.`z1`(`id`, `uname`) VALUES ('3', 'java') /*percona-toolkit src_db:test src_tbl:z1 src_dsn:P=3306,h=192.168.56.100,p=...,u=wanbin dst_db:test dst_tbl:z1 dst_dsn:P=3306,h=mysqldb2,p=...,u=wanbin lock:1 transaction:1 changing_src:test.checksums replicate:test.checksums bidirectional:0 pid:4374 user:root host:mysqldb1*/;

#參數解釋:
--replicate= :指定經過pt-table-checksum獲得的表,這2個工具差很少都會一直用。
--databases= : 指定執行同步的數據庫。
--tables= :指定執行同步的表,多個用逗號隔開。
--sync-to-master :指定一個DSN,即從的IP,他會經過show processlist或show slave status 去自動的找主。
h= :服務器地址,命令裏有2個ip,第一次出現的是Master的地址,第2次是Slave的地址。
u= :賬號。
p= :密碼。
--print :打印,但不執行命令。
--execute :執行命令。


#execute修復命令
pt-table-sync --replicate=test.checksums h=192.168.56.100,u=wanbin,p=mysql,P=3306 h=192.168.56.200,u=wanbin,p=mysql,P=3306 --execute


#再使用pt-table-checksum


# pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=test.checksums --create-replicate-table --databases=test --tables=z1 h=192.168.56.100,u=wanbin,p=mysql,P=3306
Checking if all tables can be checksummed ...
Starting checksum ...
            TS ERRORS  DIFFS     ROWS  DIFF_ROWS  CHUNKS SKIPPED    TIME TABLE
09-19T16:11:50      0      0        2          0       1       0   0.134 test.z1


【注意】:要是表中沒有惟一索引或則主鍵則會報錯:
Can't make changes on the master because no unique index exists at /usr/local/bin/pt-table-sync line 10591.

4.2 錯誤號1032處理

1032錯誤:主庫更新或者刪除的記錄在從庫上不存在。

模擬錯誤

1. slave上刪除數據 mysql> set sql_log_bin=0; mysql> select * from z1; +----+-------+ | id | uname | +----+-------+ | 2 | mysql | | 3 | java | +----+-------+ 2 rows in set (0.00 sec) mysql> delete from z1 where id=3; 2. master上更新數據 mysql> update z1 set uname='python' where id=3; 3. 查看slave status mysql> show slave status\G ... Last_SQL_Errno: 1032 Last_SQL_Error: Could not execute Update_rows event on table test.z1; Can't find record in 'z1', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log my3306_binlog.000076, end_log_pos 974253816 Read_Master_Log_Pos: 974253847 ... Exec_Master_Log_Pos: 974253510 ... 1. slave上刪除數據 mysql> set sql_log_bin=0; mysql> select * from z1; +----+-------+ | id | uname | +----+-------+ | 2 | mysql | | 3 | java | +----+-------+ 2 rows in set (0.00 sec) mysql> delete from z1 where id=3; 2. master上更新數據 mysql> update z1 set uname='python' where id=3; 3. 查看slave status mysql> show slave status\G ... Last_SQL_Errno: 1032 Last_SQL_Error: Could not execute Update_rows event on table test.z1; Can't find record in 'z1', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log my3306_binlog.000076, end_log_pos 974253816 Read_Master_Log_Pos: 974253847 ... Exec_Master_Log_Pos: 974253510 ...

修復錯誤

  1. 能夠利用pt工具進行修復
    利用pt-slave-restart,pt-table-checksum,pt-table-sync修復錯誤,這與1062錯誤的修復方法一致。

  2. 利用mysqlbinlog修復

mysql> SHOW BINLOG EVENTS in 'my3306_binlog.000076' from 974253510; +----------------------+-----------+----------------+-----------+-------------+-------------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +----------------------+-----------+----------------+-----------+-------------+-------------------------------------------+ | my3306_binlog.000076 | 974253510 | Anonymous_Gtid | 1003306 | 974253575 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | | my3306_binlog.000076 | 974253575 | Query | 1003306 | 974253647 | BEGIN | | my3306_binlog.000076 | 974253647 | Rows_query | 1003306 | 974253710 | # update z1 set uname='python' where id=3 | | my3306_binlog.000076 | 974253710 | Table_map | 1003306 | 974253758 | table_id: 132 (test.z1) | | my3306_binlog.000076 | 974253758 | Update_rows | 1003306 | 974253816 | table_id: 132 flags: STMT_END_F | | my3306_binlog.000076 | 974253816 | Xid | 1003306 | 974253847 | COMMIT /* xid=1153364 */ | +----------------------+-- cd /data/mysql/mysql3306/logs mysqlbinlog -v --base64-output=decode-rows --start-position=974253510 --stop-position=974253847 my3306_binlog.000076 ... ### UPDATE `test`.`z1` ### WHERE ### @1=3 ### @2='java' ### SET ### @1=3 ### @2='python' ... #在slave上,根據binlog日誌,在slave上插入對應數據。 insert into test.z1 values(3,'java') #查看slave status mysql>show slave status\G ... Slave_IO_Running: Yes Slave_SQL_Running: Yes ... mysql> SHOW BINLOG EVENTS in 'my3306_binlog.000076' from 974253510; +----------------------+-----------+----------------+-----------+-------------+-------------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +----------------------+-----------+----------------+-----------+-------------+-------------------------------------------+ | my3306_binlog.000076 | 974253510 | Anonymous_Gtid | 1003306 | 974253575 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | | my3306_binlog.000076 | 974253575 | Query | 1003306 | 974253647 | BEGIN | | my3306_binlog.000076 | 974253647 | Rows_query | 1003306 | 974253710 | # update z1 set uname='python' where id=3 | | my3306_binlog.000076 | 974253710 | Table_map | 1003306 | 974253758 | table_id: 132 (test.z1) | | my3306_binlog.000076 | 974253758 | Update_rows | 1003306 | 974253816 | table_id: 132 flags: STMT_END_F | | my3306_binlog.000076 | 974253816 | Xid | 1003306 | 974253847 | COMMIT /* xid=1153364 */ | +----------------------+-- cd /data/mysql/mysql3306/logs mysqlbinlog -v --base64-output=decode-rows --start-position=974253510 --stop-position=974253847 my3306_binlog.000076 ... ### UPDATE `test`.`z1` ### WHERE ### @1=3 ### @2='java' ### SET ### @1=3 ### @2='python' ... #在slave上,根據binlog日誌,在slave上插入對應數據。 insert into test.z1 values(3,'java') #查看slave status mysql>show slave status\G ... Slave_IO_Running: Yes Slave_SQL_Running: Yes ...

另外也能夠利用bin2sql閃回修復數據,進行修復,操做以下。

#在slave上 > select * from z1; +----+--------+ | id | uname | +----+--------+ | 2 | mysql | | 3 | python | +----+--------+ 2 rows in set (0.00 sec) >delete from z1 where id=3; #在master上 > update z1 set uname='java' where id=3; #查看slave status狀態 Last_SQL_Errno: 1032 Last_SQL_Error: Could not execute Update_rows event on table test.z1; Can't find record in 'z1', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log my3306_binlog.000076, end_log_pos 974254151 Replicate_Ignore_Server_Ids: > show binary logs; +----------------------+------------+ | Log_name | File_size | +----------------------+------------+ ... | my3306_binlog.000018 | 1049112225 | +----------------------+------------+ #解析出標準SQL python binlog2sql.py -h192.168.56.200 -uwanbin -pmysql --start-file='my3306_binlog.000018' --start-datetime='2018-09-20 15:00:00' --sql-type DELETE DELETE FROM `test`.`z1` WHERE `uname`='python' AND `id`=3 LIMIT 1; #start 1049111962 end 1049112194 time 2018-09-20 15:06:58 #生成回滾語句 python binlog2sql.py --flashback -h192.168.56.200 -uwanbin -pmysql --start-file='my3306_binlog.000018' --start-datetime='2018-09-20 15:00:00' --sql-type DELETE INSERT INTO `test`.`z1`(`uname`, `id`) VALUES ('python', 3); #start 1049111962 end 1049112194 time 2018-09-20 15:06:58 #在slave上執行 INSERT INTO `test`.`z1`(`uname`, `id`) VALUES ('python', 3); #啓動複製 start slave; #在slave上 > select * from z1; +----+--------+ | id | uname | +----+--------+ | 2 | mysql | | 3 | python | +----+--------+ 2 rows in set (0.00 sec) >delete from z1 where id=3; #在master上 > update z1 set uname='java' where id=3; #查看slave status狀態 Last_SQL_Errno: 1032 Last_SQL_Error: Could not execute Update_rows event on table test.z1; Can't find record in 'z1', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log my3306_binlog.000076, end_log_pos 974254151 Replicate_Ignore_Server_Ids: > show binary logs; +----------------------+------------+ | Log_name | File_size | +----------------------+------------+ ... | my3306_binlog.000018 | 1049112225 | +----------------------+------------+ #解析出標準SQL python binlog2sql.py -h192.168.56.200 -uwanbin -pmysql --start-file='my3306_binlog.000018' --start-datetime='2018-09-20 15:00:00' --sql-type DELETE DELETE FROM `test`.`z1` WHERE `uname`='python' AND `id`=3 LIMIT 1; #start 1049111962 end 1049112194 time 2018-09-20 15:06:58 #生成回滾語句 python binlog2sql.py --flashback -h192.168.56.200 -uwanbin -pmysql --start-file='my3306_binlog.000018' --start-datetime='2018-09-20 15:00:00' --sql-type DELETE INSERT INTO `test`.`z1`(`uname`, `id`) VALUES ('python', 3); #start 1049111962 end 1049112194 time 2018-09-20 15:06:58 #在slave上執行 INSERT INTO `test`.`z1`(`uname`, `id`) VALUES ('python', 3); #啓動複製 start slave;
相關文章
相關標籤/搜索