共计 1144 个字符,预计需要花费 3 分钟才能阅读完成。
这篇“MySQL 如何批量更新死锁”文章的知识点大部分人都不太理解,所以丸趣 TV 小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“MySQL 如何批量更新死锁”文章吧。
表结构如下:
CREATE TABLE `user_item` ( `id` BIGINT(20) NOT NULL,
`user_id` BIGINT(20) NOT NULL,
`item_id` BIGINT(20) NOT NULL,
`status` TINYINT(4) NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_1` (`user_id`,`item_id`,`status`)) ENGINE=INNODB DEFAULT CHARSET=utf-8
SQL 语句如下:
update user_item set status=1 where user_id=? and item_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 上的锁,这样就出现了死锁。
解决方案:
先获取需要更新的记录的主键
select id from user_item where user_id=? and item_id=?
逐条更新
update user_item set status=? where id=? and user_id=?
批量循环重复第一步和第二步即可
以上就是关于“MySQL 如何批量更新死锁”这篇文章的内容,相信大家都有了一定的了解,希望丸趣 TV 小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注丸趣 TV 行业资讯频道。
正文完