Mysql RDS alter table enum短暂中断了我的数据库连接

a8jjtwal  于 5个月前  发布在  Mysql
关注(0)|答案(1)|浏览(60)

上下文

我们使用RDS MySQL 8.0。
我们有一个高吞吐量的写/读表。昨天我们确实发出了一个alter table语句来修改enum的值。我们在枚举列表at the end of the list中添加了一个值。我们用no lockinplace算法完成了它。现在过去,我们曾经这样做,它曾经工作得很好,在毫秒内完成。但是昨天花了一个多小时。完成的表大小是42 GB。当这个操作完成时,我可以看到我们得到了很多Lock wait timeout exceeded; try restarting transaction'
这提示我在这个操作的最后阶段发生了某种形式的表锁定。我不能把我的手指放在上面。这里到底发生了什么。

调查

link的故事
只要数据类型的存储大小不变,就可以通过在有效成员值列表的末尾添加新枚举或集合成员来修改ENUM或SET列的定义。例如,向具有8个成员的SET列添加成员会将每个值所需的存储从1字节更改为2字节;这需要一个表副本。在列表中间添加成员会导致现有成员重新编号,这需要一个表副本。
这就是当时RDS Performance Insight对此事务的显示
x1c 0d1x的数据
在此期间,RDS性能见解中的另一个等待片段



列排序规则是utf8_unicode_ci现在基于上面,我试图看看我们的ENUM值中的值的存储要求是什么。



现在上图的最后一行是我们添加的。所以我可以看到这里的存储需求确实发生了变化。所以我们现在需要至少42个字节的枚举,如果我理解正确的话。所以根据mysql文档,复制表可能会触发,这可能解释了行为。

Question现在我的问题是,如果上面的解释确实是正确的,那么添加一个比最后一个更长的值(根据字符串值中的字符数)(基本上比当前集合中的最长值更长)必须重现这种行为。但是如果我再添加一个字符,那么它就不能重现了。我错过了什么?我如何解释锁等待?

envsm3lx

envsm3lx1#

如果你将一个NOT NULL列修改为NULL,那么修改一个列也会触发一个表复制,反之亦然。我看到在你的alter命令中,你将该列设置为nullable。在你修改它之前,它是NOT NULL吗?
事实上,该列之前是NOT NULL的,但在这次更改中它被设置为NULL!
如果您需要在生产环境中创建一个ALTER TABLE,这将导致在一个大表上进行表复制,我建议使用一个开源的在线模式更改工具。这意味着表复制在后台运行,您可以在此期间继续读取和写入表。

当然,与任何新工具一样,首先在测试环境中使用它-而不是在生产环境中-直到您有信心使用它。
在我之前的工作中,我们使用pt-online-schema-change每周在生产环境中运行数百个模式更改,而不会阻塞任何应用程序。

相关问题