learn and grow up

mysql诡异的死锁问题排查及分析全过程记录二之RR的锁

字数统计: 739阅读时长: 3 min
2020/10/02 Share

写在前面

​ 接上文,本文主要讲述RR锁的概念和场景

正文

  1. innodb默认隔离级别为RR,本服务用的也是RR,所以我们重点来看下RR相关的东西

    假如有如下表:

    1
    2
    3
    4
    5
    CREATE TABLE `lotest` (
    `type` varchar(20) NOT NULL,
    `name` varchar(255) NOT NULL DEFAULT '1',
    KEY `idx_order_id` (`type`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  1. RR解决了脏读和不可重复读、及大部分场景的幻读。解决的方案是什么呢?就是mvcc解决不可重复读问题。mvcc+gap+record+next-key(record+gap)锁解决幻读问题。

    1. mvcc:后面需要细说,它大概的方案如下:每条记录都有隐藏的trxid来标示当前记录版本号,查询时维护一个readview,用来记录全局的事务的前后顺序,再结合当前事务id,然后结合undo(历史版本记录)来判断当前事务需要访问哪些版本的记录。这样就可以使得一个事务内访问的数据都是一个版本的,不会因为其他事务干扰而select数据不同。如下:

      1. 步骤 事务1 事务id 结果 事务2
        1 select * from lotest where type=20; trxId=1 value =1
        2 select * from lotest where type=20; trxId=2 value =1
        3 update lotest set value = 2 where type =20; trxId=3
        4 select * from lotest where type=20; trxId=3 value=2
        5 select * from lotest where type=20; trxId=1 value =1
    2. record x 锁

      1. 比如库中有两条记录:

        type name

        A20 4
        A10 3

      2. 进行如下步骤

        1. 步骤 事务1 结果 事务2
          1 update lotest set name = 4 where type =’A20’; success
          2 insert into lotest (type) values(‘A20’);/update lotest set name = 4 where type =’A20’; Waiting
      3. 然后使用语句查看lock日志,

        1
        2
        3
        4
        5
        6
        7
        8
        9
        SELECT

        FROM
        INFORMATION_SCHEMA.INNODB_LOCKS;
        SELECT *
        FROM
        information_schema.innodb_trx

        show engine innodb status;

        结果如下:

        被锁影响的事务

        被锁影响的事务明细

        insert引擎日志

        update引擎日志

    3. gap(间隙锁)举例

      比如库中有两条记录:

      type name

      A20 4
      A10 3

      进行如下操作

      步骤 事务1 结果 事务2
      1 update lotest set name = 4 where type =’A15’; success
      2 insert into lotest (type) values(‘A16’); Waiting

      然后使用语句查看lock日志,日志如下:

      被锁影响的事务

      被锁影响的事务明细

      引擎日志

      通过日志可以看到,如果根据索引去更新(delete、update)不存在的数据,那么innodb会定位该不存在的数据相邻的两个索引,并加上X gap锁,X gap锁不互斥,其他事务也可以申请x gap锁,如

      步骤 事务1 事务2
      1 update lotest set name = 4 where type =’A15’; success
      2 update lotest set name = 4 where type =’A16’; success

      但是其他事务却不能申请权限大于x gap锁,如插入意向锁和x锁,就如上面截图所示的结果,一致等待最初的事务commit。

    4. Next-key锁

      1. 他是record x 锁和gap x锁的集合。如下

        1. 步骤 事务1 事务2 结果
          1 update lotest set name = 4 where type <=’A20’; success
          2 insert into lotest (type) values(‘A16’); Gap x
          3 update lotest set name = 4 where type =’A20’; Record x

      逻辑和前面两种锁一样,这里就不细说了,也不截图了。

      未完待续……

CATALOG
  1. 1. 写在前面
  2. 2. 正文