MySQL 千万级别大数据量的表添加新字段时踩的坑

时间:2024-04-06 22:45:55

MySQL 大表数据 添加新字段

最近在升级一个老的mysql项目时需要在一张老表:t_order_goods中添加是否虚拟商品标示字段:isVirual,开发人员在自己的开发环境完美的做好加字段操作,并成功提交到测试环境,测试人员也在预发布环境完美的测试通过,然后在发布生产当天意外出现了。。。具体细节请仔细看下文

发布环节

公司的DBA同事接到开发的加字段的脚本:
alter table t_order_goods add column isVirtual int default 0;

看到此脚本,也么有任何问题,资深的DBA同事就直接Execute了,然后出乎大家意料的是 竟然执行此脚本时客户端MySQLWorkbench超时了,意味着第一次执行失败了!
然后我们的DBA同事 查了下该表的数据量,大概在一千万,分析了下 可能是数据量大导致加字段超时了,于是毫不犹豫 查了度娘 调整了客户端 MySQLWorkbench的超时时间
MySQL 千万级别大数据量的表添加新字段时踩的坑

最后觉得查不到调整到十分钟应该可以执行完吧,就改了此配置,然而还是意外发生了,第二次执行还是超时了,第二次失败!
可是我们的DBA 可是资深的哦 还是不甘心哦,继续调整了此参数改为半小时,觉得一千万数据在他的认知里 肯定能执行完,调整完参数后 又happy的等着执行结果,然后大家失望的是还是失败了,这已经是第三次失败了!
时间就这样一分一秒的很快过去了! 晚上八点开始执行发布的任务,差不多到快21:00还没有发布成功。。。大家的心开始慌了。。。

分析原因

1、首先第一个问题是生产环境执行失败,开发+预发布环境都可以执行成功,大家一致的意见就是表:t_order_goods数据量几个环境不一样,生产环境数据量偏大
2、生产环境MySQL的版本是5.7 ,出现几次失败 项目组的开发人员都很积极去度娘,发现MySQL5.xx版本之前都有类似的问题,凡事大数据表 添加字段都会很慢,一旦执行添加字段操作 严重的会拖垮整个数据库服务器;而8.0.xx之后的版本引入了新的算法,基本上执行加字段操作很快,几乎是毫秒级的操作
题外话,我们的DBA同事是专业的资深SQL Server专家,对MySQL不是特别擅长,本次发布也是对MySQL又是狠狠的鄙视

解决方案

找到了问题的原因后,大家为了快速的发布上线,准备了备用计划:
方案一、扩展新表方案
1、扩展一张新的表,t_order_goods_ext ,添加关联t_order_goods表的字段good_id, 是否虚拟商品标示字段:isVirtual
2、将涉及到本次业务的虚拟商品goodId初始化到扩展表中,不用迁移t_order_goods老表的数据,这样数据量瞬间很小了
3、调整应用层的程序调用代码,将涉及到操作t_order_goods表的地方改为左关联扩展表t_order_goods_ext
方案二、老表数据迁移四部曲方案
1、新建老表t_order_goods的备份表t_order_goods_bak,同时加一个字段:isVirtual 并给默认值
2、迁移老表t_order_goods数据到备份表t_order_goods_bak中
3、删除老表t_order_goods
4、新命名备份表t_order_goods_bak表名为t_order_goods
以上的操作步骤2~4建议是在脱机的情况下执行,避免在执行迁移数据过程中有新数据进来,导致新表数据流失不完整
方案三、升级MySQL的服务器版本
1、将现有MySQL版本5.7升级到8.0.12之后的版本
2、然后再执行添加字段操作

以上几个方案优势劣势对比
方案一:
优势:开发人员可以快速的定位相关影响点
劣势: 一旦新表的数据量一样的会耗时很长
方案二:
优势:不用再调整业务层的应用程序代码,只需要DBA迁移表即可
劣势:新表可能会跟老表数据不一致,数据不完整;脱机操作过长可能会影响其他业务的正常运行
方案三:
优势:不影响业务层的应用程序代码,也不会导致数据丢失
劣势:升级过程,必然要脱机,此过程时间过程一样会影响业务的正常运行

经验总结

个人建议在实际情况允许的情况下,如果大家所在的公司也出现类似的问题时,尽可能的还是采用方案三:升级服务器版本
毕竟长远考虑,后续在业务的发展不确定情况下,原始表拓展加新的字段是很正常的一件事,升级到高版本后 因为引入了新的算法:即时算法 所以会毫秒级别的加字段 不会对业务发布上线造成影响
具体引入的即时算法:instant 在稍后的章节做详细阐述~~