美文网首页
Innodb存储引擎--锁整理

Innodb存储引擎--锁整理

作者: 迷途的华生 | 来源:发表于2015-10-23 18:08 被阅读213次

    Innodb的锁,保障了事务的隔离性;对索引(聚集索引组织表)加锁,Oracle是对数据块(堆表)加锁

    何登成的文章_基础
    何登成的文章_进阶

    锁类型

    innodb支持多粒度锁:记录级锁和表级锁;
    为了支持这种多粒度,加入意向锁(intention lock),
    意向锁是表级锁,提示事务对此表记录加的记录锁类型。

    兼容 X IX S IS
    X
    IX
    S
    IS

    1、要想获得S锁,必须先取得IS或者更强的锁
    2、要想获得X锁,必须先取得IX锁

    • 意向锁不会阻塞任何操作,除非是全表请求(alter, lock table ...)
    • 意向锁是完全兼容的,因为是表级别的,若不兼容,则innodb的行锁无从谈起
      事务1对表a的某些记录进行写操作,事务2相对表a的某另一些记录进行写操作,两者都有IX操作,若不兼容,直接退变成Myisam的表锁形式了
    • X, S 的兼容场景,针对的是同一记录区间的读写,这样就理解上面的兼容性

    锁算法(这是锁算法,不是锁类型)

    Record lock:This is a lock on an index record.
    记录锁一定是锁索引记录,即使无索引,也会使用innodb的隐藏的聚集索引

    Gap lock: *This is a lock on a gap * between index records, or a lock on the gap before the first or after the last index record.
    间隙锁唯一索引不会用到(联合唯一索引前缀过滤仍会使用),无索引和非唯一索引会使用,锁记录的前后区间

    Gap锁特性:

    不同事务对同一区间的不同记录进行插入操作,两者不冲突
    gap 区间的一条记录被删除, gap 锁要合并
    gap s == gap x ,且兼容。只阻塞插入区间操作

    Next-key lock:This is a combination of a record lock on the index record and a gap lock on the gap * before * the index record.
    举例:
    (negative infinity, 10]
    (10, 11]
    (11, 13]
    (13, 20]
    (20, positive infinity) 退化为gap lock,信息展示next_key lock

    X type record lock gap lock next_key lock
    record lock
    gap lock
    next_key lock

    不可重复读(幻读)

    一个事务内,对同一数据集合连续查询(包括非锁定读),另外一个事务对此数据集合进行了DML,本事务内结果是一致的。但不保障查询之间,本事务的DML(会有“幽灵”输出)的场景。注意,innodb读取的是查询开始的快照,不是事务开启时的快照

    锁案例

    CREATE TABLE testlock (
    a int(11) NOT NULL DEFAULT '0',
    b int(11) DEFAULT NULL,
    PRIMARY KEY (a),
    KEY b (b)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
    select * from testlock;
    +----+------+
    | a | b |
    +----+------+
    | 2 | 1 |
    | 5 | 3 |
    | 6 | 5 |
    | 10 | 8 |
    +----+------+

    • 有值加锁
      select * from testlock where b=3 for update

    由图例可以看出:
    索引b,加了next_key lock (1,3] 和 gap lock(3,5)
    主键a,加了一个record lock a=5

    有值加锁
    • 无值加锁
      select * from testlock where b=2 for update
      由图例可以看出:
      索引b,加了gap lock (1,3)
      无值加锁.png
    • 临界加锁
    • select xxxx from where b xxx for update
      select * from testlock where b=8 for update
      (5,8],(8, +∞)。
      select * from testlock where b>8 for update
      select * from testlock where b>80 for update
      锁全表
    临界加锁
    • delete from where b xxx
      delete from testlock where b=8
      此种情况,与上面的一致,加锁(5,8],(8, +∞)。截图与上面的模式相同
      delete from testlock where b> 8
      此种情况,加next_key lock (8, +∞)。图例准确
    • upate where b xxx
      update testlock set a=9 where b=6
      update testlock set b=10 where b=6
      update涉及对索引的自身值得改写操作,存在锁分裂的情况,不一而足

    当然,跟组合四:[id无索引, Read Committed]类似,这个情况下,MySQL也做了一些优化,就是所谓的semi-consistent read。semi-consistent read开启的情况下,对于不满足查询条件的记录,MySQL会提前放锁。针对上面的这个用例,就是除了记录[d,10],[g,10]之外,所有的记录锁都会被释放,同时不加GAP锁。semi-consistent read如何触发:要么是read committed隔离级别;要么是Repeatable Read隔离级别,同时设置了innodb_locks_unsafe_for_binlog 参数。更详细的关于semi-consistent read的介绍,可参考我之前的一篇博客:MySQL+InnoDB semi-consitent read原理及实现分析

    相关文章

      网友评论

          本文标题:Innodb存储引擎--锁整理

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