从模拟数据到场景复现,剖析 MySQL Online DDL 异常报错之谜

云掣YunChe6个月前最新动态391

本文从模拟数据到场景复现,深入浅出的分享了 MySQL 在线 DDL 变更误触报错的原因分析和解决方案,以减少或避免在Online DDL操作中误触发异常错误,提高数据库变更的成功率,希望能对遇到相似问题的客户起到一定的帮助。云掣专注于可观测运维,为您的数字化转型保驾护航~

前言

业务执行一条 alter table table_name engine=innodb 失败了很多次,一直无法执行成功,报错 ERROR 1062 (23000): Duplicate entry xxx for key 'xxx',在官方文档中也提到过,Online DDL 期间可能会出现 ERROR 1062 (23000): Duplicate entry 异常,但是没有详细说明,什么情况下会触发。业务执行 DDL 的时候,一直没有成功,意味着距离找到答案不远了。

When running an in-place 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 DML operations 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.

https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-limitations.html

1. 模拟现场

1.1 测试表结构

CREATE TABLE `ddl_test` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) NOT NULL,
  `channel_id` tinyint(4) NOT NULL,
  `version` bigint(20) NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `user_info` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unq_index` (`user_id`,`channel_id`,`version`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


1.2 制造测试数据

mysql_random_data_load 是使用 Go 语言开发的 MySQL 随机造数工具,可从下方链接中直接下载编译完成的二进制程序。

下载地址:mysql_random_data_load GitHub

08a7c9c1106c664cf3dfc5e3f14c1182.png

下载对应系统版本的文件,开箱即用。

# 解压后会得到一个二进制程序
tar -zxvf mysql_random_data_load_0.1.12_Linux_x86_64.tar.gz
# 验证
./mysql_random_data_load --help


造数命令模版:

mysql_random_data_load -h127.0.0.1 -u'用户' -p'密码' --max-threads=线程数 库名 表名 造数多少行

造数工具准备好了,现在需要制造一些测试数据,便于观测现象。

mysql_random_data_load -h127.0.0.1 -u'test' -p --max-threads=10 test ddl_test 2000000

1.3 场景复现

截图_20250114173810.png

让人疑惑的是,Session 1 第二次写入并没有成功,为什么会导致 DDL 执行失败呢?

2. 原因分析

经过源码分析,发现 MySQL Online DDL 期间所有的写入都会记录到增利日志中,增量日志是通过聚簇索引(主键)来校验唯一性,只要主键不冲突后就直接写入到增量日志中,然后再依次写唯一索引、二级索引。

image.png

此时唯一索引由于违反约束,执行失败,抛出异常,增量日志这里也没有进行回滚,造成在 Online DDL 合并阶段,违反唯一索引的记录会被合并到表里,造成 DDL 执行失败。

image (1).png

3. 如何解决

了解到业务是一个并发写入的场景,会偶发导致重复写入的问题,定位到业务场景后,通过降低了并发,减少了重复写入。最后 DDL 执行成功。如果遇到该问题,建议先定位问题是由于哪些 SQL 造成的,然后和业务侧配合规避掉这个异常。

4. 误导报错

经过测试在 MySQL 5.7.17 版本复现该问题的时候,会出现一个误导报错。虽然是由 unq_index 约束造成的,在 DDL 会话里面,会直接报错主键的值,并且这个自增主键值不存在,因为已经被回滚了,回滚后自增主键不会重新分配了,会让用户一头雾水。

root@mysql  [deom]>alter table ddl_test engine=innodb, ALGORITHM=INPLACE, LOCK=NONE;
ERROR 1062 (23000): Duplicate entry '200006' for key 'PRIMARY'

后记

经过测试,该问题在最新的长期支持版本 MySQL 8.4 中依然存在。

云掣专注于可观测运维,致力解决企业上云难、用云难、管云难三大问题。基于云数据库提供7*24小时保障服务,提供开发支持、数据库体系规范、持续优化、数据库架构支持,保障企业数据库高效稳定运行。全面提升企业的运维效率和稳定性,助力企业完成云时代的数字化转型,满足客户在数据库管理和云迁移方面的多样化需求!



相关文章

袋鼠云CEO宁海元:打通数智基建到应用的通路,让数据不再“躺灰” | 数据猿专访

袋鼠云CEO宁海元:打通数智基建到应用的通路,让数据不再“躺灰” | 数据猿专访

一家大型制造企业的老板最近心情颇为复杂。几年前,企业投入巨资构建数据存储和治理系统,如今数据确实源源不断地积累,但他发现,这些数据似乎并没有带来预期的业务收益。虽然存储成本逐年攀升,但数据依旧沉睡在系...

MySQL数据库线程池泄露场景解决方案

MySQL数据库线程池泄露场景解决方案

在数字化时代,数据是企业的核心资产,而数据库则是存储和管理这些资产的重要仓库。本文通过云掣为某信息化管理行业客户快速解决MySQL数据库故障的案例,详细的分享了MySQL数据库出现问题时的解决思路和具...

ACOS可观测运维套件—容器监控

ACOS可观测运维套件—容器监控

一、简介ACOS统一运维监控平台最新4.0版本支持容器能力,对于容器数据采集成功后会上报到控制台「容器监控」,您可以查看到租户内容器各种对象的数据信息。容器数据有两种查看和分析模式,通过切换页面左上角...

云掣科技亮相2024云栖大会,让用云更简单、更安全

云掣科技亮相2024云栖大会,让用云更简单、更安全

2024年云栖大会于9月19日-9月21日召开,今年大会以“云启智跃,产业蝶变”为主题,吸引大模型、自动驾驶、机器人等领域的400多家国内外企业来到现场,共同展示AI时代云上创新的潮流科技。大会设置了...

ACOS统一监控之达梦数据采集

ACOS统一监控之达梦数据采集

署名-汪勇(苏夏)一、前言基于目前的互联网环境趋势和国家的倡导,在将来软件基础新的工具或应用国产化是一大方向。而在运维可视化这个行业来说,我们ACOS产品也是需要达梦数据的运行状态做一定的监控,从而完...

可观测领域系列之存储分析鉴赏Talk(Part 1)

可观测领域系列之存储分析鉴赏Talk(Part 1)

前面有文章也提到过,可观测领域目前尚存的一些短板,其中存储分析就是其一,只能根据过往的一些经验,以及调研分析来尝试帮大家鉴赏下当前这个领域的一些技术和竞品分析。在分析这个问题之前,我们先从场景出发,以...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。