美文网首页
mysql SERIALIZABLE隔离级别死锁问题

mysql SERIALIZABLE隔离级别死锁问题

作者: littlersmall | 来源:发表于2017-04-19 21:06 被阅读869次

    最近的项目,为了保障绝对的一致性,使用SERIALIZABLE作为隔离级别。
    然后就爆出了很诡异的死锁。
    报错log如下:

    org.springframework.dao.DeadlockLoserDataAccessException: PreparedStatementCallback; SQL [xxxxx]; Deadlock found when trying to get lock; 
    try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
    1461 2017-04-17 21:58:26.550 ERROR pool-7-thread-2 
    

    我们的sql大概是这样的:

    begin;
    
    select * from table_a where id = 6;
    
    INSERT INTO  xxx  (xxxxx)  ON DUPLICATE KEY UPDATE xxxxx;
    
    UPDATE table_a SET column_a = GREATEST(column_a, 0)  WHERE id = 6;
    
    commit;
    

    报错的概率并不高,在我们的系统中,大概只有2%的概率左右出现。

    单独执行这段sql并不会有任何问题,因此定位了许久。后来灵光一下,同时开启两个事务来模拟这个操作。
    方式如下:

    //准备工作
    1 set session transaction isolation level SERIALIZABLE;
    2 create table user (id int PRIMARY KEY, age int) engine = innodb;
    3 insert into user values(1, 2);
    

    分别开启两个事务

    //事务A
    begin;
    select * from user wherer id = 1;
    //A level_1
    update user set age = 3 where id = 1;
    //A level_2
    commit;
    
    //事务B
    begin;
    select * from user wherer id = 1;
    //B level_1
    update user set age = 3 where id = 1;
    //B level_2
    commit;
    

    两个事务同时开启,当执行到level_1的时候停住,注意观察数据库的输出

    level_1

    这个时候一切正常
    我们继续往下执行事务A,如图

    level_2.png
    我们发现事务A卡住了。
    再继续执行事务B,死锁出现了。 dead_lock.png

    原因:
    究其原因,是SERIALIZABLE隔离级别读写锁竞争导致的。
    在SERIALIZABLE级别下,不会使用mysql的mvcc机制,而是在每一个select请求下获得读锁,在每一个update操作下尝试获得写锁。
    在我们的例子中,在level_1中,事务A获得了id = 1的读锁A。
    而在同时,事务B获得id = 1的读锁B。
    在事务A level_2时,事务A尝试获得id = 1的写锁,这个时候,由于id = 1处不仅有事务A的读锁,还有事务B的读锁,因此事务A的update操作获取锁被阻塞。
    此时,当事务B继续执行update操作时,由于事务A又拥有id = 1的读锁A,因此进入互相等待状态,造成死锁。

    解决方案:
    1 将select操作改为select for update,直接加写锁。
    2 在业务层将此种类事务串行化。

    相关文章

      网友评论

          本文标题:mysql SERIALIZABLE隔离级别死锁问题

          本文链接:https://www.haomeiwen.com/subject/xwwhzttx.html