MySQL · 捉虫动态·DROP DATABASE外键约束的GTID BUG

简介: 背景 MySQL的DDL没有被设计成事务操作,因此DDL操作是无法回滚的(像PgSQL把DDL也设计成事务操作,DDL就可以在执行成功后被回滚操作取消)。这就会导致如果某个DDL语句内部被拆分为多个原子的DDL调用,那么这个DDL语句就不具备中途执行失败后回滚整个DDL语句的能力,也就是说,即使语

背景

MySQL的DDL没有被设计成事务操作,因此DDL操作是无法回滚的(像PgSQL把DDL也设计成事务操作,DDL就可以在执行成功后被回滚操作取消)。这就会导致如果某个DDL语句内部被拆分为多个原子的DDL调用,那么这个DDL语句就不具备中途执行失败后回滚整个DDL语句的能力,也就是说,即使语句逻辑内的某个原子DDL调用失败了,也无法回滚已经完成的那些原子DDL调用。


问题描述

DROP DATABASE 就是一个例子,对于MySQL而言,DROP DATABASE 并非是一个原子DDL操作,因为它是一个个删除DB下的每张表,而 DROP TABLE 操作本身是会做预检查的,无法删除就会取消删表操作返回失败,所以 DROP TABLE 才能认为是原子的DDL调用。 这就会引起一个问题,如果一个DB中的某张表DROP失败了,实际上 DROP DATABASE 作为一个整体是执行失败的,但是DB中已经有一些表被删除了,因此Binlog中会记录成多个 DROP TABLE 操作,而不是一个 DROP DATABASE 语句。 如果被删除的表的表名都不长,还是会记录成一个删除多张表的 DROP TABLE 语句(DROP TABLE tbl1, tbl2, ...),但是如果表名总长度太长,MySQL会拆分为多个 DROP TABLE 语句来记录。 没有GTID的时候这似乎也不是什么大问题,但是引入GTID之后就有一个问题:每个语句只分配一个GTID。如果一个 DROP DATABASE 语句被拆分为多个 DROP TABLE 语句,Binlog中就会出现多个 DROP TABLE 事件共用一个GTID的情况!

举个例子:

 

这里因为 db2.t3 表引用了 db1.t1 的字段作为外键约束,所以当 db1 做 DROP DATABASE 删除到 t1 表时就报错了,但此时很多表已经被删除了。我们看Binlog中记录的内容:

 

3个 DROP TABLE 语句都是同一个GTID:340d95b8-a699-11e4-868d-a0d3c1f20ae4:61

这就导致备库复制报错:

 


解决方案

怎么解决这个问题呢?

1. 让MySQL支持DDL事务

2. 对DROP DATABASE操作进行预检查


第一种方案对MySQL改动太大了,完全不现实。因此我们采用了第二种方案,也间接实现了 DROP DATABASE 这个操作的原子性。 DROP DATABASE 之所以出现上面的状况,就是因为没有先检查表是否可以删除,而是走一步看一步,一个个删的时候才看能不能删除。我们对MySQL做了修正,对于DB中的每张表,在 DROP DATABASE 执行之前,都先预检查所有可能导致删除表失败的条件,如果一旦发现某张表会无法删除,就放弃整个 DROP DATABASE 操作,提示用户删除错误,让用户先自行解决问题后,再重新执行 DROP DATABASE。

例如上面例子中的情况,本来 DROP DATABASE 执行到有外键约束的表时会报错:

 

但此时其他表已经删除了,而我们修正以后,同样的操作会报一个Error和一个Warning,并且没有真的删任何表:

 

这里提示了用户有表存在问题无法删除,让用户先处理掉之后,再来执行 DROP DATABASE。此时库下面所有的表都还在,一定要预检查通过才会真的删除。


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
4月前
|
存储 安全 关系型数据库
MySQL数据库约束条件概述及其重要性讨论。
正确地实现并管理好各类紧缩条件将直接影响到企业信息管理水平与服务质量,在当今大数据背景下更显得格外重要;任何设计师都需要深刻理解其原理与运作机晰承担起责任使得所托管资料安全稳固同时又具备良好伸缩灵活度迎合日益复杂商务需求变动.
185 11
|
SQL 前端开发 关系型数据库
全表数据核对 ,行数据核对,列数据核对,Mysql 8.0 实例(sample database classicmodels _No.3 )
全表数据核对 ,行数据核对,列数据核对,Mysql 8.0 实例(sample database classicmodels _No.3 )
316 0
全表数据核对 ,行数据核对,列数据核对,Mysql 8.0 实例(sample database classicmodels _No.3 )
|
NoSQL 关系型数据库 MySQL
2024Mysql And Redis基础与进阶操作系列(4-2)作者——LJS[含MySQL非空、唯一性、PRIMARY KEY、自增列/自增约束举例说明等详解步骤及常见报错问题对应的解决方法]
24MySQL非空、唯一性、PRIMARY KEY、自增列/自增约束举例说明等详解步骤及常见报错问题对应的解决方法(4-2) 学不会你来砍我!!!
|
12月前
|
存储 SQL 关系型数据库
【MySQL基础篇】MySQL约束语法
文章介绍了MySQL中表的约束概念,包括非空、唯一、主键、默认和外键约束,以及如何在创建和修改表时指定这些约束。外键约束用于保持数据的一致性和完整性,文章通过示例展示了添加、删除外键的语法,并讨论了不同的删除/更新行为,如CASCADE和SETNULL。
【MySQL基础篇】MySQL约束语法
|
关系型数据库 MySQL 数据处理
MySQL函数与约束
MySQL 提供了丰富的函数和强大的约束机制,用于数据处理和完整性维护。通过掌握这些工具,可以有效地管理和分析数据库中的数据,确保数据的一致性和准确性。无论是在日常数据查询中使用内置函数,还是在数据库设计中应用各种约束,都是确保数据库系统稳定、高效运行的关键。希望本文对您理解和应用 MySQL 函数与约束有所帮助。
184 1
|
12月前
|
存储 关系型数据库 MySQL
MySQL(条件约束)
为了校验数据,让数据的正确性能够得到保证,约束,能够引进更多的检查操作,但是也会增加系统的成本开销
|
关系型数据库 MySQL 数据库
mysql 8.0 递归(例子分享)(sample database classicmodels _No.4)
本文介绍了如何在MySQL8.0中使用递归查询处理部门表和员工表的树形结构数据,包括查看文档、准备数据、递归处理以及提取层级信息。作者通过示例展示了WITHRECURSIVE语句的应用及其在数仓中的结构表示。
240 2
|
安全 关系型数据库 MySQL
mysql8.0 正值表达式Regular expressions (sample database classicmodels _No.5)
本文介绍了MySQL8.0中的正值表达式及其相关函数,通过实例展示了如何使用正则表达式进行字符串匹配,并提出了关于执行效率的问题。
330 1
|
SQL 关系型数据库 MySQL
介绍5款 世界范围内比较广的 5款 mysql Database Management Tool
介绍5款 世界范围内比较广的 5款 mysql Database Management Tool
660 0
|
3月前
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
165 3

相关产品

  • 云数据库 RDS MySQL 版
  • 推荐镜像

    更多