当前位置: 首页 > MySQL数据库

MySQL如何批量更新死锁

时间:2026-01-25 16:19:43

表结构如下:

CREATETABLE`user_item`(`id`BIGINT(20)NOTNULL,`user_id`BIGINT(20)NOTNULL,`item_id`BIGINT(20)NOTNULL,`status`TINYINT(4)NOTNULL,PRIMARYKEY(`id`),KEY`idx_1`(`user_id`,`item_id`,`status`))ENGINE=INNODBDEFAULTCHARSET=utf-8

SQL语句如下:

updateuser_itemsetstatus=1whereuser_id=?anditem_id=?

原因分析:

mysql的事务支持与存储引擎有关,MyISAM不支持事务,INNODB支持事务,更新时采用的是行级锁。这里采用的是INNODB做存储引擎,意味着会将update语句做为一个事务来处理。前面提到行级锁必须建立在索引的基础,这条更新语句用到了索引idx_1,所以这里肯定会加上行级锁。行级锁并不是直接锁记录,而是锁索引,如果一条SQL语句用到了主键索引,mysql会锁住主键索引;如果一条语句操作了非主键索引,mysql会先锁住非主键索引,再锁定主键索引。

这个update语句会执行以下步骤:

    由于用到了非主键索引,首先需要获取idx_1上的行级锁

    紧接着根据主键进行更新,所以需要获取主键上的行级锁;

    更新完毕后,提交,并释放所有锁。

如果在步骤1和2之间突然插入一条语句:update user_item …..where id=? and user_id=?,这条语句会先锁住主键索引,然后锁住idx_1。

蛋疼的情况出现了,一条语句获取了idx_1上的锁,等待主键索引上的锁;另一条语句获取了主键上的锁,等待idx_1上的锁,这样就出现了死锁。

解决方案:

    先获取需要更新的记录的主键

    selectidfromuser_itemwhereuser_id=?anditem_id=?

    逐条更新

    updateuser_itemsetstatus=?whereid=?anduser_id=?

    批量循环重复第一步和第二步即可


上一篇:linux中如何使用tar包安装MySQL
下一篇:MySQL怎么实现类型转换
mysql
  • 英特尔与 Vertiv 合作开发液冷 AI 处理器
  • 英特尔第五代 Xeon CPU 来了:详细信息和行业反应
  • 由于云计算放缓引发扩张担忧,甲骨文股价暴跌
  • Web开发状况报告详细介绍可组合架构的优点
  • 如何使用 PowerShell 的 Get-Date Cmdlet 创建时间戳
  • 美光在数据中心需求增长后给出了强有力的预测
  • 2027服务器市场价值将接近1960亿美元
  • 生成式人工智能的下一步是什么?
  • 分享在外部存储上安装Ubuntu的5种方法技巧
  • 全球数据中心发展的关键考虑因素
  • 英特尔与 Vertiv 合作开发液冷 AI 处理器

    英特尔第五代 Xeon CPU 来了:详细信息和行业反应

    由于云计算放缓引发扩张担忧,甲骨文股价暴跌

    Web开发状况报告详细介绍可组合架构的优点

    如何使用 PowerShell 的 Get-Date Cmdlet 创建时间戳

    美光在数据中心需求增长后给出了强有力的预测

    2027服务器市场价值将接近1960亿美元

    生成式人工智能的下一步是什么?

    分享在外部存储上安装Ubuntu的5种方法技巧

    全球数据中心发展的关键考虑因素