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

云掣YunChe8个月前最新动态591

本文从模拟数据到场景复现,深入浅出的分享了 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小时保障服务,提供开发支持、数据库体系规范、持续优化、数据库架构支持,保障企业数据库高效稳定运行。全面提升企业的运维效率和稳定性,助力企业完成云时代的数字化转型,满足客户在数据库管理和云迁移方面的多样化需求!



相关文章

ACOS统一监控之自动化巡检

ACOS统一监控之自动化巡检

作者:晓风引言随着信息技术的发展和普及,企业的 IT 系统已经成为企业运营的重要组成部分。在这些系统中,应用程序和服务的可用性和性能对业务运营至关重要。然而,IT 系统的复杂性和规模,以及 IT 运维...

EasyTwin:全方位升级,打造高质量数智化孪生应用

10月30日,袋鼠云“AI驱动,数智未来”主题秋季发布会成功落幕。在这场盛会中,我们一起深度探讨了如何凭借 AI 实现新的飞跃,重塑企业的经营管理方式,加速数智化进程。在发布会现场,展示了众多集成AI...

指标+AI+BI,袋鼠云构建智能数据分析新范式

指标+AI+BI,袋鼠云构建智能数据分析新范式

10月30日,袋鼠云成功举办了以“AI驱动,数智未来”为主题的2024年秋季发布会。大会深度探讨了如何凭借 AI 实现新的飞跃,重塑企业的经营管理方式,加速数智化进程。作为大会的重要环节之一,袋鼠云数...

正式发布 | 《云运维服务白皮书》开放下载!

正式发布 | 《云运维服务白皮书》开放下载!

在全球数字化变革的背景下,为适应数字经济环境下企业生存发展和市场变化的需要,企业进行主动的、系统性、整体性的数字化转型升级。大数据、云计算、人工智能、区块链等新一代信息通信技术为企业的数字化转型提供了...

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

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

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

应对复杂架构下的监控挑战?统一运维可观测能力是关键!

在全球数字化变革背景下,企业需适应数字经济与市场变化,进行系统性数字化转型。在“十四五”规划指导下,企业纷纷探求数字化应用之路,大数据、云计算、人工智能、区块链等技术成了热门话题,其中云运维备受瞩目。...

发表评论    

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