美文网首页
MySQL存储引擎InnoDB2-锁

MySQL存储引擎InnoDB2-锁

作者: 梦工厂 | 来源:发表于2018-03-16 12:06 被阅读48次

    锁:为了支持对于共享资源的并发访问,提供数据的完整性和一致性。

    1 lock vs latch (这一章讲的是lock)

    lock 的对象是事务,用来锁定的是数据库中的对象,如表、页、行.
    一般lock的对象仅在事务commit或者rollback后释放(不同隔离级别释放时间不同);


    2 InnoDB中的锁
    2.1. 锁的类型
    • 行级锁:锁定索引
      共享锁S:允许事务读一行数据。
      排他所X:允许事务删除或更新一行数据。
    • 意向锁:
      支持在不同粒度上加锁,行级和表级上的锁同时存在。
      InnoDB的意向锁就是表锁,主要是为了在一个事务中揭示下一行将被请求的锁类型;
      意向共享锁 IS:事务想要获取一张表中的某几行的共享锁。
      意向排他锁 IX:事务想要获取一张表中的某几行的排他锁。
    • IS IX S X
      IS 兼容 兼容 兼容 不兼容
      IX 兼容 兼容 不兼容 不兼容
      S 兼容 不兼容 兼容 不兼容
      X 不兼容 不兼容 不兼容 不兼容
      锁的兼容性:一个事务拿到锁之后另一个事务能不能拿到锁。
      IS IX S X
      IS 兼容 兼容 兼容 不兼容
      IX 兼容 兼容 不兼容 不兼容
      S 兼容 不兼容 兼容 不兼容
      X 不兼容 不兼容 不兼容 不兼容
    2.2. 一致性非锁定读 MVCC

    通过读取快照数据,实现读写并行


    1)快照数据是该行之前版本的数据,通过undo段来实现。而undo用来在事务中回滚数据,因此快照数据没有额外开销。此外,读取快照数据是不需要上锁的,因为没有事务需要对快照数据进行修改操作。
    2)MVCC是默认的读取方式,即读取不会占用和等待表上的锁。
    在不同的隔离级别下,读取的方式不同,并不是在每个事务隔离级别下都是采用MVCC读。
    此外,即使都是MVCC读,对于快照数据的定义在不同隔离级别也各不相同。
    • 隔离级别为可重复读时:InnoDB使用MVCC读,对于快照数据,总是读取事务开始时的行数据版本;
    • 隔离级别为读已提交时:InnoDB使用MVCC读,对于快照数据,总是读取被锁定行的最新一份快照数据;
    2.3. 一致性锁定读

    某些情况下,需要显示对读取操作进行加锁以保证数据的一致性。 (隔离级别更高了,读也要加锁)
    对select语句加X锁:select ... for update
    对select语句加S锁:select ... lock in share mode

    3 外键和锁
    • Innodb中,对于外键列,如果没有显示加索引,会自动对其添加一个索引,因此避免表锁。
    • 对于外键值的插入或更新,首先需要查询父表记录,select父表。此时并不是采用MVCC读的方式,而是选择了select ... lock in share mode主动对父表加S锁。如果此时父表上已经加X锁,子表操作被阻塞。
      考虑:父表删除id操作,子表插入新纪录外键select父表选择MVCC就会产生不一致的情况。
    4 行锁的算法
    1. Record Lock :单个行记录上的锁
    2. Gap Lock: 间隙锁,锁定一个范围,但不包含记录本身;(锁定的是两边的间隙,不能插进来)
    3. Next-Key Lock: Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身。
      辅助理解 MySQL 加锁处理分析
    5 死锁

    死锁是指两个或两个以上的事务在执行过程中,因争夺资源而造成的一种互相等待的现象。
    解决方法:

    1. 超时机制,优点是简单,缺点是未能考虑事务的执行情况。
    2. 等待图 wait-for-group ,InnoDB采取这种方式。
      等待图 要求数据库保留两种信息:锁的事务链表,事务等待链表。

      根据上述信息构造出一张图,如果存在回路代表存在死锁。
      图中,事务1指向事务2的边定义为:
      (1)事务1等待被事务2所占用的资源;
      (2)事务1最终等待事务2所占用的资源,即事务12在等待相同的资源,而事务1在事务2后边;

      等待图是一种主动的死锁检测机制,每个事务请求锁的时候都会判断是否存在回路,若存在则死锁,通常InnoDB选择回滚undo量最小的事务。
    6 补充总结
    1. MySQL Innodb存储引擎的并发控制方式:Lock-Based Concurrency Control + MVCC
      在MVCC并发控制中,读操作可以分成两类:快照读 (snapshot read)与当前读 (current read)。快照读,读取的是记录的可见版本 (有可能是历史版本),不用加锁。当前读,读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。
    2. 2PL:Two-Phase Locking
      传统RDBMS加锁的一个原则,就是2PL (二阶段锁):Two-Phase Locking
      锁操作分为两个阶段:加锁阶段与解锁阶段,并且保证加锁阶段与解锁阶段不相交。

      2PL就是将加锁/解锁分为两个完全不相交的阶段。加锁阶段:只加锁,不放锁。解锁阶段:只放锁,不加锁。
    3. 分析SQL语句加锁情况:MySQL 加锁处理分析
    4. 参考书《MySQL技术内幕 InnoDB存储引擎 第2版》

    @梦工厂 2018.3.16

    相关文章

      网友评论

          本文标题:MySQL存储引擎InnoDB2-锁

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