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;
相关文章
相关标签/搜索