故障处理报告–mysql5.7 online ddl bug:
数据库版本:
mysql 5.7
背景:
早晨同事在执行mysql 数据表磁盘空间整理工作(回收数据文件空间碎片),期间执行了ddl操作,ddl操作报如下错误:
error 1062(23000): duplicate entry 'xxx' for key 'key_name'
排查过程:
-
查看数据是否重复
show create table table_name -- 略的表结构定义: create table 'table_name' ( ... 'order_code' varchar(64) collate utf8mb4_bin default null, ... unique key 'order_idx' ('order_code') using btree, ) engine-innodb ...
发现报错的key 是一个unique key, 根据unqiue key 的定义,该字段不可能存在重复的entry。从下图的查询结果也能确定表中该字段的值均是唯一的。遂不可能是表中数据出现了问题。
-
查询资料
通过查询资料发现m6米乐安卓版下载官网有如下的一段描述:
when running an online ddl operation, the thread that runs the alter table statement applies an
online log of dml operations that were run concurrently on the same table from other connection
threads. when the dmloperations are applied, it is possible to encounter a duplicate key entry
error (error 1062 (23000): duplicate entry), even if the duplicate entry is only temporary and
would be reverted by a later entry in the online log. this is similar to the idea of a foreign
key constraint check in innodb in which constraints must hold during a transaction.
描述所说 online ddl 期间,其他会话执行的dml操作造成唯一键冲突的sql会记录到 online log 中,在commit阶段等变更结束之后再应用这些sql会导致报错唯一键冲突。
注意: 资料来源于https://www.cnblogs.com/igoodful/p/14075649.html
-
根据理论寻找支持
此error 1062(23000) 错误是由其它会话执行造成唯一键冲突,那么数据库一定会返回给该会话error 1062(23000)错误,通过应用日志查找该错误。经过查找错误日志,发现数据库确实返回给了应用一个一摸一样的唯一键冲突报错:如下截图:
然后继续排查应用日志,是什么操作导致了唯一键的重复,最后通过开发排查是用户短时间内将相同数据提交了两遍。 所以在数据提交前最好数据验证非常重要。
-
模拟bug
第一步:session a: 执行alter table ddl 操作;
| 第二步:session b: 在session a 执行完毕前,构造并执行能触发重复键的dml语句(update、insert),并提交;
第三步:session a: 等待session a 报错,查看sessiona 报错是否与session b 一致。
总结:
不管任何数据库,做重大的ddl操作,需要在业务低峰期操作或停业务操作(能不online,就不建议online操作),生产环境稳定为第一要素。