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

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介:

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为全局变量
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
关系型数据库 MySQL 数据库
mysql卸载、下载、安装(window版本)
mysql卸载、下载、安装(window版本)
|
1月前
|
关系型数据库 MySQL Linux
Linux启动停止重启Mysql数据库针对各个版本的数据库
Linux启动停止重启Mysql数据库针对各个版本的数据库
10 0
|
2月前
|
存储 关系型数据库 MySQL
linux环境安装8.0以上版本的MySQL详细教程(亲测好用)
linux环境安装8.0以上版本的MySQL详细教程(亲测好用)
75 0
|
3月前
|
存储 关系型数据库 MySQL
【MySQL进阶之路丨第十三篇】一文带你精通MySQL之ALTER命令及序列使用
【MySQL进阶之路丨第十三篇】一文带你精通MySQL之ALTER命令及序列使用
41 0
|
4月前
|
关系型数据库 MySQL
若依框架----如何降低mysql驱动版本?
若依框架----如何降低mysql驱动版本?
60 3
|
2月前
|
关系型数据库 MySQL 数据库
django4版本提示 django.db.utils.NotSupportedError: MySQL 8 or later is required (found 5.7.26)
在学习Django时,用户遇到`django.db.utils.NotSupportedError`,提示需要MySQL 8.0.25或更高版本,但其系统上是5.7.26。为解决这个问题,用户决定不升级MySQL,而是选择注释掉Django源码中的数据库版本检查。通过Python命令行找到Django安装路径,进入`db/backends/base/base.py`,注释掉`self.check_database_version_supported()`函数
217 0
|
2月前
|
SQL 关系型数据库 MySQL
【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(8.0版本升级篇)
【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(8.0版本升级篇)
102 0
|
3月前
|
存储 关系型数据库 MySQL
MySQL技能完整学习列表5、数据库操作——1、创建数据库和表——2、修改表结构(ALTER TABLE)
MySQL技能完整学习列表5、数据库操作——1、创建数据库和表——2、修改表结构(ALTER TABLE)
186 0
|
12天前
|
关系型数据库 MySQL Shell
备份 MySQL 的 shell 脚本(mysqldump版本)
【4月更文挑战第28天】
23 0
|
2月前
|
关系型数据库 MySQL Linux
Linux安装MySQL(只针对这个8.0版本其他版本的MYSQL不知道是不是也可以用可以自己尝试)
Linux安装MySQL(只针对这个8.0版本其他版本的MYSQL不知道是不是也可以用可以自己尝试)
28 0