MySQL 5.6 Online DDL异常分析

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介:

0、导读

MySQL 5.6里,按理说是可以支持Online DDL的,为啥在给一个表增加字段/增加索引时,却把该表上的DML给阻塞了呢?

1、问题

我的朋友小明,在使用Percona 5.6.30版本,想要对一个表增加辅助索引,想着MySQL 5.6版本的Online DDL功能应该比较强大了,不会有啥问题吧,就放心的提交 DDL 命令了,结果悲剧了,后续的 DML 都被阻塞了,看下现场:


图1

小明当时就懵逼了,不是说MySQL 5.6里,增加字段/增加索引的DDL是可以Online的吗,为毛他提交的DDL就把DML给阻塞了呢。无奈之中小明又找到我来求助了~

2、排查

看了上面的 图.1,不知道各位看官有没有觉得哪里不对劲呢?先按下不表。

在MySQL 5.6中,提交DDL命令后,正常的话,该线程状态应该是altering table 、committing alter table to storage engine 这样的才对,为啥是 copy to tmp table 呢,说明这个 DDL 不是IN-PLACE的。

我们先看下这三种状态分别怎么解释的:

  • altering table

The server is in the process of executing an in-place ALTER TABLE.

  • committing alter table to storage engine

The server has finished an in-place ALTER TABLE and is committing the result.

  • copy to tmp table

The thread is processing an ALTER TABLE statement. This state occurs after the table with the new structure has been created but before rows are copied into it.

光看线程状态解释好像还是不甚明了,于是让小明干脆在测试环境再尝试模拟增加索引,然后查看线程状态,还是 copy to tmp table。不过测试表数据量比较大,增加索引过程比较久,小明没啥耐心,就按了CTRL-C 把 DDL 命令给终止了,然后终端提示下面的信息:


图2

咦,好像疑点更多了。

我问小明这个实例是怎么来的,是不是从旧版本数据文件直接拷贝过来用的。经提醒,小明才道出这个实例的数据库文件原来是在MariaDB 5.5环境下运行的,后来直接升级到MariaDB 10.0,再后来为了兼容 GTID 问题(MariaDB和官方 GTID 不兼容这点是挺麻烦的),所以把版本切换成 Percona 5.6.30。

现在终于明白了,原来是因为旧版本的数据文件中,存在着 TIME、DATETIME、TIMESTAMP 数据类型,从MySQL 5.6开始,这几个数据类型底层存储格式发生了变化(增加了对毫秒的支持)。

所以,MySQL发现该表中,存在旧格式的 DATETIME 列,就需要强制进行升级,也就没办法执行 IN-PLACE 的 DDL 了,才有了后面的 DML 锁等待。

关于从旧版本升级到MySQL 5.6及以上,几个注意事项请查阅官方文档说明:

  • http://dev.mysql.com/doc/refman/5.6/en/checking-table-incompatibilities.html

  • http://dev.mysql.com/doc/refman/5.6/en/upgrading-from-previous-series.html


回过头来再说上面提到的 copy to tmp table 状态,就是要因为需要升级数据结构,所以需要重建整张表。

3、解决

问题找到了,解决问题的办法也得想到才行呀。方法有三,暴力的 和 非暴力的。

先说下暴力的吧,其实和本例差不多,就是强制执行一次DDL,让表结构升级下,这个过程是不支持 IN-PLACE 的,必须重建整张表。比如官方推荐的方法之一:

ALTER TABLE tbl_name FORCE;

还有一种就是用 mysqldump 把数据从旧版本中备份出来,再在新版本环境中导入加载,效率和第一种不相上下。

再说下非暴力的,这是从MySQL 5.6.24才引入的功能,新增了一个 avoid_temporal_upgrade 选项,其作用是让我们能选择是否强制升级表结构,看看该选项的描述:

This variable controls whether ALTER TABLE implicitly upgrades temporal columns found to be in pre-5.6.4 format (TIME, DATETIME, and TIMESTAMP columns without support for fractional seconds precision). Upgrading such columns requires a table rebuild, which prevents any use of fast alterations that might otherwise apply to the operation to be performed.


This variable is disabled by default. Enabling it causes ALTER TABLE not to rebuild temporal columns and thereby be able to take advantage of possible fast alterations.


This variable was added in MySQL 5.6.24. It is deprecated and will be removed in a future MySQL release.



文章转自老叶茶馆公众号,原文链接:https://mp.weixin.qq.com/s/2CpIx_4tC27g6er-JaC4ZQ

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
0
192
分享
相关文章
MySQL如何优雅的执行DDL
在MySQL中优雅地执行DDL操作需要综合考虑性能、锁定和数据一致性等因素。通过使用在线DDL工具、分批次执行、备份和监控等最佳实践,可以在保障系统稳定性的同时,顺利完成DDL操作。本文提供的实践和案例分析为安全高效地执行DDL操作提供了详细指导。
134 14
MySQL 更新1000万条数据和DDL执行时间分析
MySQL 更新1000万条数据和DDL执行时间分析
419 4
"MySQL增列必锁表?揭秘InnoDB在线DDL,让你的数据库操作飞一般,性能无忧!"
【8月更文挑战第11天】在数据库领域,MySQL凭借其稳定高效的表现深受开发者喜爱。对于是否会在给数据表添加列时锁表的问题,MySQL的行为受版本、存储引擎等因素影响。从5.6版起,InnoDB支持在线DDL,可在改动表结构时保持表的可访问性,避免长时间锁表。而MyISAM等则需锁表完成操作。例如,在使用InnoDB的表上运行`ALTER TABLE users ADD COLUMN email VARCHAR(255);`时,通常不会完全锁表。虽然在线DDL提高了灵活性,但复杂操作或大表变更仍可能暂时影响性能。因此,进行结构变更前应评估其影响并择机执行。
137 6
Mysql Online DDL
Mysql Online DDL
105 2
MySQL基础(一) 前置安装以及DDL详解
MySQL基础(一) 前置安装以及DDL详解
90 1
MySQL数据库—初识数据库 | DDL语句 | DML语句
MySQL数据库—初识数据库 | DDL语句 | DML语句