从库跳过gtid
环境:
OS:Centos 7
DB:mysql 5.7.29
同步启用GTID模式
1.确保目前同步是正常的
2.主库上创建表
CREATE TABLE `tb_test01` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name1` varchar(32) DEFAULT NULL,
`name2` varchar(32) DEFAULT NULL,
`name3` varchar(32) DEFAULT NULL,
`name4` varchar(32) DEFAULT NULL,
`name5` varchar(32) DEFAULT NULL,
`name6` varchar(32) DEFAULT NULL,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1;
写入数据
insert into tb_test01(name1) values('name1');
insert into tb_test01(name1) values('name1');
insert into tb_test01(name1) values('name1');
insert into tb_test01(name1) values('name1');
insert into tb_test01(name1) values('name1');
insert into tb_test01(name1) values('name1');
insert into tb_test01(name1) values('name1');
insert into tb_test01(name1) values('name1');
insert into tb_test01(name1) values('name1');
insert into tb_test01(name1) values('name1');
这个时候是正常同步的.
3.模拟主从不一致
从库上删除一条数据
delete from tb_test01 where id=10;
然后主库上执行删除id=10的记录
delete from tb_test01 where id=10;
这个时候查看从库的状态,提示报错误,找不到id=10的记录.
show slave status \G;
输出部分:
Last_SQL_Errno: 1032
Last_SQL_Error: Could not execute Delete_rows event on table db_test.tb_test01; Can't find record in 'tb_test01', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log binlog.000001, end_log_pos 19739427
Retrieved_Gtid_Set: 9ecf61e2-eed1-11ed-a4b0-080027e81195:1-26 ##从库接收到主库的gtid,9ecf61e2-eed1-11ed-a4b0-080027e81195为主库的uuid
Executed_Gtid_Set: 636915ca-ef98-11ed-a854-080027962264:1-836,##从库自己的gitd,mysql_home/data/auto.cnf可以获取到数据库的uuid,该gtid在从库上有事务操作才会变化,正常同步下该值不变化
9ecf61e2-eed1-11ed-a4b0-080027e81195:1-21 ##从库已经执行的gtid,这个时候停在了gtid=21,已经接收到gtid=26的,但是因为错误的原因无法继续执行
那么我们要跳过gitd=22(21+1)的事务,确保gtid=22(21+1)就是我们主库删除的那个事务,可以分析binlog日志
主库上执行
/opt/mysql57/bin/mysqlbinlog -vv --base64-output=decode-rows /opt/mysql57/mysqllog/binlog/binlog.000001>/tmp/aa01.txt
cat /tmp/aa01.txt
找到gitd=22的事务,这里确实是主库删除id=10的事务
SET @@SESSION.GTID_NEXT= '9ecf61e2-eed1-11ed-a4b0-080027e81195:22'/*!*/;
# at 19739212
#230511 5:14:12 server id 1 end_log_pos 19739287 CRC32 0x900f9382 Query thread_id=45 exec_time=0 error_code=0
SET TIMESTAMP=1683796452/*!*/;
BEGIN
/*!*/;
# at 19739287
#230511 5:14:12 server id 1 end_log_pos 19739365 CRC32 0x277a89a3 Table_map: `db_test`.`tb_test01` mapped to number 140
# at 19739365
#230511 5:14:12 server id 1 end_log_pos 19739427 CRC32 0x595142cb Delete_rows: table id 140 flags: STMT_END_F
### DELETE FROM `db_test`.`tb_test01`
### WHERE
### @1=10 /* LONGINT meta=0 nullable=0 is_null=0 */
### @2='name1' /* VARSTRING(128) meta=128 nullable=1 is_null=0 */
### @3=NULL /* VARSTRING(128) meta=128 nullable=1 is_null=1 */
### @4=NULL /* VARSTRING(128) meta=128 nullable=1 is_null=1 */
### @5=NULL /* VARSTRING(128) meta=128 nullable=1 is_null=1 */
### @6=NULL /* VARSTRING(128) meta=128 nullable=1 is_null=1 */
### @7=NULL /* VARSTRING(128) meta=128 nullable=1 is_null=1 */
### @8='2023-05-11 05:11:45' /* DATETIME(0) meta=0 nullable=0 is_null=0 */
### @9='2023-05-11 05:11:45' /* DATETIME(0) meta=0 nullable=0 is_null=0 */
# at 19739427
#230511 5:14:12 server id 1 end_log_pos 19739458 CRC32 0x4893b453 Xid = 6301095
COMMIT/*!*/;
# at 19739458
#230511 5:15:14 server id 1 end_log_pos 19739523 CRC32 0xc4431a04 GTID last_committed=22 sequence_number=23 rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
从库上执行跳过该事务:
mysql> stop slave;
mysql> set GTID_NEXT='9ecf61e2-eed1-11ed-a4b0-080027e81195:22';
mysql> begin;commit;
mysql> set GTID_NEXT='AUTOMATIC';
mysql> start slave;
4.若主库上的binlog已经清理掉了,但是没有同步到从库,那么从库会缺失不只一个事务了,会缺失很多的事务组,这样的话可以使用如下方式跳过这些事务组(这时数据主从已经不一致了),事务组之间使用分号分隔
stop slave;
reset master;
set global gtid_purged='c5689ee2-f2bb-11ed-aef4-080027ab879d:214-262,c5689ee2-f2bb-11ed-aef4-080027ab879d:1-113,c5689ee2-f2bb-11ed-aef4-080027ab879d:263';
start slave;