千家信息网

mysql insert into ... select的死锁问题是什么

发表于:2025-11-10 作者:千家信息网编辑
千家信息网最后更新 2025年11月10日,小编给大家分享一下mysql insert into ... select的死锁问题是什么,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧!问题产生:系统中mysql里面有几个event,每
千家信息网最后更新 2025年11月10日mysql insert into ... select的死锁问题是什么

小编给大家分享一下mysql insert into ... select的死锁问题是什么,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧!

问题产生:

系统中mysql里面有几个event,每几分钟就会执行一次,用来统计数据之类的功能,然后这个event里面会往一张表里面写入数据。 大致内容: replace into a from select 需要的字段 from b; 大体结构是这样,select 需要的字段from b这里是简写,实际上非常复杂,有很多表的join的操作。然后这个event是每一分钟就执行一次,在数据量很大的情况下 一分钟可能还执行不完。然后我们会有其他的各种插入,更新的操作去对b表进行操作。此时就会发现,后端日志里面经常会有deadlock和wait lock timeout的报错, 最后测试发现把event关掉就没有这个问题,基本确认是这个event的问题。

问题分析:

其实最耗时的是发现是event的问题,查询资料解决问题并没有花太多时间。 1.首先根据后端日志里面的报错信息定位到是哪张表产生了死锁,是哪张表等待锁超时
2.然后根据这几个表名和打印的sql找到了大概可能是哪里的问题,大致确认了是event中的sql导致的
3.再验证我们的想法,把event关掉后发现日志就没有lock的问题了
4.检查event中的语句发现大概就是replace into a from select 需要的字段 from b;

这里主要是不太清楚mysql哪些情况会上锁,理论上select的操作只会上一个共享锁,对于b表的插入和更新等操作是上排他锁, 这两个是可以兼容的,一个读一个写,并不冲突。但是根据等到所超时的现象上来看,就像是select 需要的字段 from b把b表也给锁住了, 所以插入和更新都在等待锁。

最后在Stack Overflow中找到了有一点眉目的信息,链接地址。 这里说要设置成read-committed的级别就可以了。然后也引出了一个mysql配置参数:innodb_locks_unsafe_for_binlog。

于是我们顺着这个信息从官网上去查看,发现有这么一段话:

INSERT INTO T SELECT ... FROM S WHERE ... sets an exclusive index record lock (without a gap lock) on each row inserted into T. If the transaction isolation level is READ COMMITTED, or innodb_locks_unsafe_for_binlog is enabled and the transaction isolation level is not SERIALIZABLE, InnoDB does the search on S as a consistent read (no locks). Otherwise, InnoDB sets shared next-key locks on rows from S. InnoDB has to set locks in the latter case: During roll-forward recovery using a statement-based binary log, every SQL statement must be executed in exactly the same way it was done originally.复制代码

意思是说对于INSERT INTO T SELECT ... FROM S WHERE ...这种情况首先T表上会家伙是哪个记录锁(行级锁),并且是不带间隙锁的。 对于表S,有两种情况下不会加锁:
1.如果事务隔离级别为READ COMMITTED
2.或者启用了innodb_locks_unsafe_for_binlog且事务隔离级别不是SERIALIZABLE的

否则,InnoDB在S的行上设置共享的next-key。如果不清楚next-key的话可以看下官网的这个介绍,链接地址。

因此我们要解决所等待超时的方式已经比较明朗了,就是让S表不要被锁住,然而不要被锁住可以使用官网说的两种方式。 这两种都可以,但是根据innodb_locks_unsafe_for_binlog这个参数的介绍来看最好是使用方式1,将事务的隔离级别设置为read-committed。

原因有下面几点:
1.是innodb_locks_unsafe_for_binlog这个参数是静态的,必须要在my.cnf中加入一行innodb_locks_unsafe_for_binlog = 1,然后重启数据库才能生效。 在mysql中输入命令:

show variables like "%innodb_locks_unsafe_for_binlog%"复制代码

如果发现是ON就是开启成功了。
2.事务的隔离级别粒度比较细,可以针对某个session来设置,不同的session可以用不同的隔离级别,而且这个参数是动态的直接在mysql命令行修改就行。
3.mysql5.7的参数介绍中说,innodb_locks_unsafe_for_binlog这个参数将在后面的mysql版本中废弃掉。这个说的是实话,我去查看了mysql8.0的参数详解发现已经没有这个参数了。

所以推荐使用事务隔离级别来控制。

看完了这篇文章,相信你对mysql insert into ... select的死锁问题是什么有了一定的了解,想了解更多相关知识,欢迎关注行业资讯频道,感谢各位的阅读!

问题 参数 级别 隔离 事务 字段 情况 数据 死锁 信息 就是 方式 日志 更新 不同 代码 命令 地址 篇文章 链接 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 网络安全论文常见答辩问题 智慧美业软件开发公司电话 服务器维保合同模板免费下载 兰大软件开发专业全国排名 剑与远征会有一堆服务器吗 软件开发优先级分几级 网络技术进行美术教学的利与弊 我的世界服务器新手礼包复制指令 h3c服务器怎么开启管理口 修改win10 网络安全设置 湖北浪潮服务器维修哪家好 软件开发和自学 代理服务器进不去游戏 网络技术客观题 河南拓嘉网络技术科技有限公司 app本地数据库 湖州esop软件开发 农行云音箱无法连接服务器 销售分析软件开发商 备份数据库为什么总出现错误 网络安全的五大禁止是什么 sql差数据库端口语句 怎么做内网网络安全防护 漳州市网络安全宣传活动 蜜汁炖鱿鱼网络安全吗 上海东方财富软件开发怎么样 魔兽世界npc数据库数据库 在菜鸡里怎么创建方舟服务器 php脚本数据库使用说明 汕头餐饮软件开发公司
0