【MySQL】truncate抛异常System Lock
一. 背景
表数据大概几十万,不到五十万
每隔10几分钟使用truncate清空数据,然后再写入等量数据
数据库主从结构
数据库版本5.7
二. 现象
执行truncate时从库偶发抛异常【System Lock】,非必现。占用线程资源,导致后续SQL语句全部阻塞
从库不可用,进而导致路由到该从库的请求全部阻塞,从而导致应用雪崩
三. 分析
网上搜了很多资料,都说是truncate在MySQL5.7及以下版本的bug,drop命令可以解决此问题,升级到8.0也可以解决此问题。
网上资料说数据量达到几千万才会出现此问题,实际上几十万就出现。原因可能和相关配置、系统并发量有关
MDL写锁原因(猜测?)
- 参考资料:https://time.geekbang.org/column/article/69862
- 资料中说:对表的增删改查会加MDL读锁(表级锁);对表结构做变更会加写锁(表级锁)(DDL语句),读写锁/写锁之间互斥。
- truncate属于DDL语句,即执行后会加MDL写锁(表级锁),其它对表的操作都会堵塞(包括查询),而由于truncate的一些机制(可能是bug)导致一直无法释放锁(偶发现象),结果导致【System Lock】
四. 解决思路
MySQL版本:5.7
表名:tb1
思路:使用drop 替代 truncate
方案一
- drop tb1_temp(如果存在)
- 重命名tb1为tb1_temp
- 创建新表tb1
- 写入数据到tb1
- drop tb1_temp
方案二(选中)
- drop tb1_new,tb1_bak(如果存在就删除)
- 创建表tb1_new
- 写入数据到tb1_new
- 重命名tb1到tb1_bak
- 重命名tb1_new到tb1
- drop tb1_bak
五. 结论
最终选中方案二
两者的区别在于
- 方案二的数据不一致及表不可以用的时间点在(4,5)两步。只涉及表重命名,时间较短
- 方案一的数据不一致及表不可以用的时间点在(2,3,4)两步。涉及到写入数据,时间较长
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2015-05-06 Intellij IDEA System.out.println输出中文乱码问题
2015-05-06 java_hibernate
2012-05-06 ActionResult类继承结构