• ADADADADAD

    MySQL如何批量更新死锁[ mysql数据库 ]

    mysql数据库 时间:2024-11-25 13:35:27

    作者:文/会员上传

    简介:

    表结构如下: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_

    以下为本文的正文内容,内容仅供参考!本站为公益性网站,复制本文以及下载DOC文档全部免费。

    表结构如下:

    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=?

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

    MySQL如何批量更新死锁.docx

    将本文的Word文档下载到电脑

    推荐度:

    下载
    热门标签: mysql