复制容许未来自一个MySQL数据库服务器(主服务器)的数据复制到一个或多个MySQL数据库服务器(从服务器)。 默认状况下,复制是异步的。 根据配置,您能够复制数据库中的全部数据库,所选数据库甚至选定的表。html
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
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
binlog_format
二进制日志的格式,必须使用row模式服务器
log_slave_updates
从服务器是否应将其SQL线程执行的更新记录到其本身的二进制日志中。
binlog_error_action
控制服务器没法写入二进制日志时发生的状况
在MySQL5.7.7后,默认值为ABORT_SERVER,以前版本默认值为IGNORE_ERROR
binlog-do-db
使用该参数可选择性复制数据库,如binlog-do-db=test,表示只复制test库。
binlog-ignore-db
该参数是忽略某个库的复制。如binlog-ignore-db=test,表示除了test库,其余库都复制。
gtid_mode
控制是否启用基于GTID的日志记录以及日志能够包含的事务类型
enforce_gtid_consistency
启用后,服务器经过容许仅执行可以使用GTID安全记录的语句来强制执行GTID一致性。在启用基于GTID的复制以前,必须将此选项设置为ON。
能够配置–enforce-gtid-consistency的值为:
gtid_next
指定要执行的下一个语句的GTID.
gtid_next能够采用如下任何值:
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.
非GTID模式复制,基于binlog和position方式来搭建复制。
类型 | 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,方便后期扩展。
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"
mkdir dbback20180918_163934 tar -xvf dbback20180918_163934.tar -C dbback20180918_163934
innobackupex --apply-log /data/backup/dbback20180918_163934/
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 &
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;
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;
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:
变量 | 说明 |
---|---|
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线程的延时。上述没有延时。
从库上出现写入数据,把自增id占用:1062错误
从库上出现少数据,delete,update操做时,找不到相应记录。错误号:1032
模拟故障
#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
修复错误
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上的这张表数据不一致,因此这种修复方法只能算暂时的。 #以后还需进行修复
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状态。
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.
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 ...
修复错误
能够利用pt工具进行修复
利用pt-slave-restart,pt-table-checksum,pt-table-sync修复错误,这与1062错误的修复方法一致。
利用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;