【MySQL】MySQL Insert into select 大量锁表导致无法插入

 背景

最近发现项目中有个表,越来越大 ,竟然快50G,不由得一身冷汗,看了一下代码,之前有清理策略,由于应用主节点的选举有bug,导致应用目前没有主节点,故这个表没有清理,这个表每天要新增两万左右的数据,而且有一些大字段,所以表占用的磁盘空间比较大,目前运维小哥哥给的解决方案是建个表结构相同的表a,将该表中的七天内的数据插入到表a中(Insert into a select * from 原始表 where createtime < 7天内的数据),将原始表改名为b,将a表rename为原始表的表名,方案看似天衣无缝,但是却有一个很大的坑。

问题-Q

这时候不清楚的同学可能会问,挺好的,会有什么问题呀,那不妨来看一下sql的执行计划吧,å¨è¿éæå¥å¾çæè¿°

这时,你可能看出来了,全表扫描,我们数据库的隔离级别是:提交读,全表锁死,导致无法插入,无法修改,那又有同学问,不是加了where条件吗?很显然,没有走索引呀!本来表的数据量就很大,再一全表扫描,结果可想而知,应用也不可能一直停着等待数据迁移!

解决-A

解决全表扫描让sql运行的快一些,进而达到数据迁移的目的,减少锁表的时间

目前用的where条件字段是createtime,没有索引,但是modifytime字段有索引,然后查看 代码,之前的清理策略也是用modifytime字段,索引最终方案可以改为:

1.停服务:防止应用对数据库进行写操作

2.建立替代表:建个与原始表表结构相同的表a

3.迁移数据:insert into a select * from 原始表 where modifytime < 7天内

4.rename原始表为 原始表_bak

5.rename表a为原始表名

6.启动应用服务

总结

这只是临时方案,清理策略失效的bug还是得修复的,可能有同学问,为什么不直接修复清理策略失效的bug?由于无用数据太多了,delete数据时间也很长,而且清理完之后,表空间不会释放,数据碎片还存在,清理数据碎片还会锁表,我感觉目前这种方案是最好的!前提是你的应用可以停服务!!!!!!!!!!!!!!!!!

 

老表们,问个事情,冬天天冷了,你们怎么说服自己起床的?

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值