背景说明:
在一次断网测试过程中,在主库发起了DDL操作,备库丢失该DDL,导致主从表结构不一致,接下来的测试竟然都正常,表结构不一致,不影响复制进程,感觉比较奇怪,在这之前都是认为主从表结构不一致会导致复制异常,为了弄明白这个问题,进行了问题复现验证。
测试环境
MySQL社区版 8.0.25binlog_format=row
复现过程:
在一次断网测试过程中,在主库发起了DDL操作,备库丢失该DDL,导致主从表结构不一致,接下来的测试竟然都正常,表结构不一致,不影响复制进程,感觉比较奇怪,在这之前都是认为主从表结构不一致会导致复制异常,为了弄明白这个问题,进行了问题复现验证。
MySQL社区版 8.0.25binlog_format=row
复现过程:
1、初始化8.0.25版本的两个实例,并且建立了主从复制关系,过程略
主机IP | 端口 | 角色 |
---|---|---|
10.0.0.70 | 3309 | master |
10.0.0.58 | 3309 | slave |
2、在58:3309中检查复制关系,确认正常
mysql> show slave status \G*************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.0.0.70 Master_User: repl Master_Port: 3309 Connect_Retry: 60 Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 1094 Relay_Log_File: mysql-relay-bin.000003 Relay_Log_Pos: 442 Relay_Master_Log_File: mysql-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: ...1 row in set, 1 warning (0.01 sec)
3、在70:3309中创建test库,并且创建测试表t_diff
mysql> create database test;Query OK, 1 row affected (0.00 sec)mysql> use testDatabase changedmysql> create table t_diff(id int primary key auto_increment, a varchar(10), b varchar(10), c varchar(10), d varchar(10));Query OK, 0 rows affected (0.01 sec)mysql>
4、在70:3309中,往t_diff中插入4条测试数据
mysql> insert into t_diff values(1, 'a1', 'b1', 'c1', 'd1'),(2, 'a2', 'b2', 'c2', 'd2'),(3, 'a3', 'b3', 'c3', 'd3'),(4, 'a4', 'b4', 'c4', 'd4');Query OK, 4 rows affected (0.01 sec)Records: 4 Duplicates: 0 Warnings: 0mysql>
5、模拟主从表结构不一致,在58:3309中,在t_diff中删除d列
mysql> alter table t_diff drop column d;Query OK, 0 rows affected (0.02 sec)Records: 0 Duplicates: 0 Warnings: 0mysql>
6、在70:3309中,往t_diff中更新一条记录,并且查看表中数据
mysql> update t_diff set a='a14', d='d14' where id=4;Query OK, 1 row affected (0.00 sec)Rows matched: 1 Changed: 1 Warnings: 0mysql> select * from t_diff;+----+------+------+------+------+| id | a | b | c | d |+----+------+------+------+------+| 1 | a1 | b1 | c1 | d1 || 2 | a2 | b2 | c2 | d2 || 3 | a3 | b3 | c3 | d3 || 4 | a14 | b4 | c4 | d14 |+----+------+------+------+------+4 rows in set (0.00 sec)mysql> select @@report_host;+---------------+| @@report_host |+---------------+| 10.0.0.70 |+---------------+1 row in set (0.00 sec)mysql>
7、在58:3309中,查看复制状态正常
mysql> show slave status \G*************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.230.183.70 Master_User: repl Master_Port: 3309 Connect_Retry: 60 Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 3658 Relay_Log_File: mysql-relay-bin.000003 Relay_Log_Pos: 3006 Relay_Master_Log_File: mysql-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: ...mysql>
8、在58:3309中,查看表数据条数正确
mysql> select * from test.t_diff;+----+------+------+------+| id | a | b | c |+----+------+------+------+| 1 | a1 | b1 | c1 || 2 | a2 | b2 | c2 || 3 | a3 | b3 | c3 || 4 | a14 | b4 | c4 |+----+------+------+------+4 rows in set (0.00 sec)mysql> select @@report_host;+---------------+| @@report_host |+---------------+| 10.0.0.58 |+---------------+1 row in set (0.00 sec)mysql>
9、为了查明主从执行的具体SQL,解析70:3309中最后更新的binlog信息
[root@0I /data/mysql/log]# /data/software/mysql-8.0.25-linux-glibc2.12-x86_64/bin/mysqlbinlog -vvv --base64-output=decode-rows mysql-bin.000003 | tail -n 23# at 1097#220302 9:52:15 server id 6 end_log_pos 1165 Update_rows: table id 129 flags: STMT_END_F### UPDATE `test`.`t_diff`### WHERE### @1=4 /* INT meta=0 nullable=0 is_null=0 */### @2='a4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @3='b4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @4='c4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @5='d4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### SET### @1=4 /* INT meta=0 nullable=0 is_null=0 */### @2='a14' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @3='b4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @4='c4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @5='d14' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */# at 1165#220302 9:52:15 server id 6 end_log_pos 1192 Xid = 160COMMIT/*!*/;SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;DELIMITER ;# End of log file/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;[root@0I /data/mysql/log]#
10、解析58:3309中最后插入的binlog信息
[root:/data/mysql/log]# /data/software/mysql-8.0.25-linux-glibc2.12-x86_64/bin/mysqlbinlog -vvv --base64-output=decode-rows mysql-bin.000003 | tail -n 21# at 1098#220302 9:52:15 server id 6 end_log_pos 1159 Update_rows: table id 126 flags: STMT_END_F### UPDATE `test`.`t_diff`### WHERE### @1=4 /* INT meta=0 nullable=0 is_null=0 */### @2='a4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @3='b4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @4='c4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### SET### @1=4 /* INT meta=0 nullable=0 is_null=0 */### @2='a14' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @3='b4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @4='c4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */# at 1159#220302 9:52:15 server id 6 end_log_pos 1186 Xid = 51COMMIT/*!*/;SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;DELIMITER ;# End of log file/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;[root:/data/mysql/log]#
11、解析58:3309中最后的relaylog信息
[root:/data/mysql/log]# /data/software/mysql-8.0.25-linux-glibc2.[root@pod5-hb-c3-test-31 /data/mysql/log]# /data/software/mysql-8.0.25-linux-glibc2.12-x86_64/bin/mysqlbinlog -vvv --base64-output=decode-rows mysql-relay-bin.000006 | tail -n 22#220302 9:52:15 server id 6 end_log_pos 1165 Update_rows: table id 129 flags: STMT_END_F### UPDATE `test`.`t_diff`### WHERE### @1=4 /* INT meta=0 nullable=0 is_null=0 */### @2='a4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @3='b4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @4='c4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @5='d4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### SET### @1=4 /* INT meta=0 nullable=0 is_null=0 */### @2='a14' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @3='b4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @4='c4' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */### @5='d14' /* VARSTRING(40) meta=40 nullable=1 is_null=0 */# at 1286#220302 9:52:15 server id 6 end_log_pos 1192 Xid = 160COMMIT/*!*/;SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;DELIMITER ;# End of log file/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;[root:/data/mysql/log]#
12、从上面三个日志文件解析可以得知,主库的binlog记录完整数据,从库的relay log记录完整数据,而到了从库的binlog,就只有前4个字段了,此处获得如下几个疑问?
- 1.主库、从库字段不一致,为什么可以正常同步数据
- 2.从库应用relaylog的时候,是否跳过了字段名称检查
现象解答
经过多方资料查找与咨询,最终在官方资料中找到答案,一定条件下复制结构的主、从库中表结构允许不一致,即主库相比从库多了字段、少了字段,都不影响同步,甚至在部分场景下,数据类型不一致都是可以正常同步的
经过多方资料查找与咨询,最终在官方资料中找到答案,一定条件下复制结构的主、从库中表结构允许不一致,即主库相比从库多了字段、少了字段,都不影响同步,甚至在部分场景下,数据类型不一致都是可以正常同步的