[MySQL Bug]版本<=5.1.52的MySQL在alter表时将table_map置为0,导致复制中断

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介:

RT,这是一个老bug: http://bugs.mysql.com/bug.php?id=56226
bug#56226的描述不太准确,事实上innodb同样存在问题。

低于5.1.53版本的MySQL在分别alter两个表时将table_map置为0,如果表上有触发器,这会导致在备库上的复制错误,例如如下的test case:
reset master;
drop table if exists t1;
drop table if exists t2;
drop table if exists t3;
create table t1 (a int primary key ,b int)engine=innodb;
create table t2 like t1;
create table t3 select a from t1 where 1 = 0;
alter table t2 add index (b) ;
alter table t3 add primary key(a);
delimiter //
create trigger trg_t1 after insert on t1 for each row begin
   insert into t2 (a ) values (NEW.a);insert into t3 values (NEW.a);
end;//
delimiter ;
insert into t1 values (1,2);
show binlog events;

 

| mysql-bin.000001 |  984 | Table_map   |       112 |        1026 | table_id: 68 (test.t1)                                                                                                                                                  |
| mysql-bin.000001 | 1026 | Table_map   |       112 |        1067 | table_id: 0 (test.t3)                                                                                                                                                   |
| mysql-bin.000001 | 1067 | Table_map   |       112 |        1109 | table_id: 0 (test.t2)                                                                                                                                                   |
| mysql-bin.000001 | 1109 | Write_rows  |       112 |        1147 | table_id: 68                                                                                                                                                            |
| mysql-bin.000001 | 1147 | Write_rows  |       112 |        1181 | table_id: 0                                                                                                                                                             |
| mysql-bin.000001 | 1181 | Write_rows  |       112 |        1215 | table_id: 0 flags: STMT_END_F                                                                                                                                           |
| mysql-bin.000001 | 1215 | Xid         |       112 |        1242 | COMMIT /* xid=152 */
可以看到在binlog里,被alter过的t2表和t3表的table_id都被置为0,而在备库上,rows_log_event只有通过table_id才能对应到相应的table_map,这在备库上导致混乱,复制中断。
问题产生的原因:
http://lists.mysql.com/commits/120454里已经阐述的很清楚,这里简单的描述下:
1.只有当alter操作只修改meta data时才会触发
2.patch很简单,只是将reopen_table()函数的如下一行去掉:
3085   tmp.s->table_map_id=  table->s->table_map_id;

 

在mysql_alter_table里,当打开表时:
6655      if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
(gdb) 
6657      table->use_all_columns();
(gdb) p table->s->table_map_id
$4 = 0

 

随后在完成DDL的大部分工作后,如果need_copy_table == ALTER_TABLE_METADATA_ONLY,也就是说只修改了meta data时,就需要重新打开表reopen_table
在reopen_table()里,首先调用open_unireg_entry来获取表的相关信息,然后将之前通过open_n_lock_single_table打开的表的相关信息复制给tmp:
(gdb) 
3070      if (open_unireg_entry(thd, &tmp, &table_list,
(gdb) 
3078      tmp.tablenr=          table->tablenr;
(gdb) p tmp->s->table_map_id  
$5 = 20
(gdb) n
3079      tmp.used_fields=      table->used_fields;
(gdb) 
3080      tmp.const_table=      table->const_table;
(gdb) 
3081      tmp.null_row=         table->null_row;
(gdb) 
3082      tmp.maybe_null=       table->maybe_null;
(gdb) 
3083      tmp.status=           table->status;
(gdb) 
3085      tmp.s->table_map_id=  table->s->table_map_id;
(gdb) 
3088      tmp.in_use=           thd;
(gdb) p tmp->s->table_map_id
$6 = 0

在函数open_unireg_entry中

open_unireg_entry
   |--->get_table_share_with_create
            |--->get_table_share
                    |--->assign_new_table_id(share);
                               tid= ++last_table_id;其中last_table_id为全局变量
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
0
10011
分享
相关文章
RDS用多了,你还知道MySQL主从复制底层原理和实现方案吗?
随着数据量增长和业务扩展,单个数据库难以满足需求,需调整为集群模式以实现负载均衡和读写分离。MySQL主从复制是常见的高可用架构,通过binlog日志同步数据,确保主从数据一致性。本文详细介绍MySQL主从复制原理及配置步骤,包括一主二从集群的搭建过程,帮助读者实现稳定可靠的数据库高可用架构。
159 9
RDS用多了,你还知道MySQL主从复制底层原理和实现方案吗?
vb6读取mysql,用odbc mysql 5.3版本驱动
通过以上步骤,您可以在VB6中使用ODBC MySQL 5.3驱动连接MySQL数据库并读取数据。配置ODBC数据源、编写VB6代码
82 32
MySQL主从复制 —— 作用、原理、数据一致性,异步复制、半同步复制、组复制
MySQL主从复制 作用、原理—主库线程、I/O线程、SQL线程;主从同步要求,主从延迟原因及解决方案;数据一致性,异步复制、半同步复制、组复制
311 11
MySQL版本升级(8.0.31->8.0.37)
本次升级将MySQL从8.0.31升级到8.0.37,采用就地升级方式。具体步骤包括:停止MySQL服务、备份数据目录、下载并解压新版本的RPM包,使用`yum update`命令更新已安装的MySQL组件,最后启动MySQL服务并验证版本。整个过程需确保所有相关RPM包一同升级,避免部分包遗漏导致的问题。官方文档提供了详细指导,确保升级顺利进行。
560 16
MySQL主从复制原理和使用
本文介绍了MySQL主从复制的基本概念、原理及其实现方法,详细讲解了一主两从的架构设计,以及三种常见的复制模式(全同步、异步、半同步)的特点与适用场景。此外,文章还提供了Spring Boot环境下配置主从复制的具体代码示例,包括数据源配置、上下文切换、路由实现及切面编程等内容,帮助读者理解如何在实际项目中实现数据库的读写分离。
432 1
MySQL主从复制原理和使用
mysql 5.7.x版本查看某张表、库的大小 思路方案说明
mysql 5.7.x版本查看某张表、库的大小 思路方案说明
146 5
mysql 5.7.x版本查看某张表、库的大小 思路方案说明
mysql 5.7.x版本查看某张表、库的大小 思路方案说明
111 1
Mysql中搭建主从复制原理和配置
主从复制在数据库管理中广泛应用,主要优点包括提高性能、实现高可用性、数据备份及灾难恢复。通过读写分离、从服务器接管、实时备份和地理分布等机制,有效增强系统的稳定性和数据安全性。主从复制涉及I/O线程和SQL线程,前者负责日志传输,后者负责日志应用,确保数据同步。配置过程中需开启二进制日志、设置唯一服务器ID,并创建复制用户,通过CHANGE MASTER TO命令配置从服务器连接主服务器,实现数据同步。实验部分展示了如何在两台CentOS 7服务器上配置MySQL 5.7主从复制,包括关闭防火墙、配置静态IP、设置域名解析、配置主从服务器、启动复制及验证同步效果。
285 0
Mysql中搭建主从复制原理和配置
【编程基础知识】Eclipse连接MySQL 8.0时的JDK版本和驱动问题全解析
本文详细解析了在使用Eclipse连接MySQL 8.0时常见的JDK版本不兼容、驱动类错误和时区设置问题,并提供了清晰的解决方案。通过正确配置JDK版本、选择合适的驱动类和设置时区,确保Java应用能够顺利连接MySQL 8.0。
573 1
MySQL是一个广泛使用的开源关系型数据库管理系统,它有许多不同的版本
【10月更文挑战第3天】MySQL是一个广泛使用的开源关系型数据库管理系统,它有许多不同的版本
380 5

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等