gap lock/next-key lock浅析 Basic-Paxos协议日志同步应用

http://www.cnblogs.com/renolei/p/4673842.html

当InnoDB在判断行锁是否冲突的时候, 除了最基本的IS/IX/S/X锁的冲突判断意外, InnoDB还将锁细分为如下几种子类型:

  • record lock (RK)

    记录锁, 仅仅锁住索引记录的一行

  • gap lock (GK)

    区间锁, 仅仅锁住一个区间(开区间)

  • insert intention lock (IK)

    意向插入锁

  • next key lock (NK)

    record lock + gap lock, 半开半闭区间, 且下界开, 上界闭

以下锁兼容矩阵:

request与granted之间的兼容矩阵:

         | Type of active  |
 Request |  lock (granted) |
  lock   | RK   GK  IK  NK |
---------+-----------------+
  RK     |  0   1   1  0   |
  GK     |  1   1   1  1   |
  IK     |  1   0   1  0   |
  NK     |  0   1   1  0   |


下面构造集中场景简单描述下record lock/gap lock/next-key lock

  • Table schema

    CREATE TABLE `reno` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `name` varchar(10) DEFAULT NULL,
        PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
  • 构造数据
    insert into reno select 5, ‘aa‘;
    insert into reno select 7, ‘bb‘;
    insert into reno select 9, ‘cc‘;
    insert into reno select 18, ‘dd‘;
    insert into reno select 23, ‘ee‘;
    insert into reno select 30, ‘ff‘;
    insert into reno select 40, ‘gg‘;
    insert into reno select 45, ‘hh‘;
    insert into reno select 99, ‘ii‘;
  • 查看结果
    select * from reno;
    +----+------+
    | id | name |
    +----+------+
    |  5 | aa   |
    |  7 | bb   |
    |  9 | cc   |
    | 18 | dd   |
    | 23 | ee   |
    | 30 | ff   |
    | 40 | gg   |
    | 45 | hh   |
    | 99 | ii   |
    +----+------+
    9 rows in set (0.00 sec)
  • 查看tx_isolation
    SELECT @@GLOBAL.tx_isolation, @@tx_isolation;
    +-----------------------+----------------+
    | @@GLOBAL.tx_isolation | @@tx_isolation |
    +-----------------------+----------------+
    | READ-COMMITTED        | READ-COMMITTED |
    +-----------------------+----------------+
    1 row in set (0.00 sec)

    next-key lock只有在repeatable-read级别下才有意义, 防止出现幻读

    设置tx_isolation级别为REPEATABLE-READ级别:

    SET @@GLOBAL.tx_isolation = ‘REPEATABLE-READ‘;
    Query OK, 0 rows affected (0.00 sec)
    
    SET @@SESSION.tx_isolation = ‘REPEATABLE-READ‘;
    Query OK, 0 rows affected (0.00 sec)
    
    SELECT @@GLOBAL.tx_isolation, @@tx_isolation;
    +-----------------------+-----------------+
    | @@GLOBAL.tx_isolation | @@tx_isolation  |
    +-----------------------+-----------------+
    | REPEATABLE-READ       | REPEATABLE-READ |
    +-----------------------+-----------------+
    1 row in set (0.00 sec)

  • case 1:

    sesion 1 sesion 2 sesion 2 insert status
    start transaction;    
    select * from reno where id = 9 for update;    
      start transaction;  
      insert into reno select 8,‘jj‘; ok
      insert into reno select 10,‘kk‘; ok
      insert into reno select 3,‘ll‘; ok
      insert into reno select 111,‘mm‘; ok
      rollback  
    rollback    
    • 加record lock, id = 9
  • case 2:
    sesion 1 sesion 2 sesion 2 insert status
    start transaction;    
    select * from reno where id = 15 for update;    
      start transaction;  
      insert into reno select 8, ‘jj‘; ok
      insert into reno select 10, ‘kk‘; block
      insert into reno select 16, ‘ll‘; block
      insert into reno select 19, ‘mm‘; ok
      rollback  
    rollback    
    • 加next-key lock, (9, 18]
    • innodb lock info:
      ------------
      TRANSACTIONS
      ------------
      Trx id counter 2990040255
      Purge done for trx‘s n:o < 2990040253 undo n:o < 0 state: running but idle
      History list length 323
      LIST OF TRANSACTIONS FOR EACH SESSION:
      ---TRANSACTION 0, not started
      MySQL thread id 38753, OS thread handle 0x7f377c68f700, query id 140937 localhost root init
      show engine innodb status
      ---TRANSACTION 0, not started
      MySQL thread id 9, OS thread handle 0x7f370817d700, query id 140906 127.0.0.1 root cleaning up
      ---TRANSACTION 2990040254, ACTIVE 8 sec inserting
      mysql tables in use 1, locked 1
      LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
      MySQL thread id 38773, OS thread handle 0x7f377c60e700, query id 140924 localhost root executing
      insert into reno select 10, ‘kk‘
      ------- TRX HAS BEEN WAITING 8 SEC FOR THIS LOCK TO BE GRANTED:
      RECORD LOCKS space id 64257 page no 3 n bits 80 index `PRIMARY` of table `test`.`reno` trx id 2990040254 lock_mode X locks gap before rec insert intention waiting
      Record lock, heap no 5 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
       0: len 4; hex 80000012; asc     ;;
       1: len 6; hex 0000b238648b; asc    8d ;;
       2: len 7; hex d70001c00c0110; asc        ;;
       3: len 2; hex 6464; asc dd;;
      
      ------------------
      ---TRANSACTION 2990040253, ACTIVE 17 sec
      2 lock struct(s), heap size 360, 1 row lock(s)
      MySQL thread id 38758, OS thread handle 0x7f370807b700, query id 140919 localhost root cleaning up

      从上面的trx lock信息里看到此时等待的锁是: lock_mode X locks gap before rec

  • case 3:

    sesion 1 sesion 2 sesion 2 insert status
    start transaction;    
    select * from reno where id = 200 for update;    
      start transaction;  
      insert into reno select 1, ‘jj‘; ok
      insert into reno select 88, ‘kk‘; ok
      insert into reno select 100, ‘ll‘; block
      insert into reno select 500, ‘mm‘; block
      rollback  
    rollback    
    • 加next-key lock, (99, ~)
    • innodb lock info:
      ------------
      TRANSACTIONS
      ------------
      Trx id counter 2990040257
      Purge done for trx‘s n:o < 2990040253 undo n:o < 0 state: running but idle
      History list length 323
      LIST OF TRANSACTIONS FOR EACH SESSION:
      ---TRANSACTION 0, not started
      MySQL thread id 38753, OS thread handle 0x7f377c68f700, query id 141561 localhost root init
      show engine innodb status
      ---TRANSACTION 0, not started
      MySQL thread id 9, OS thread handle 0x7f370817d700, query id 141535 127.0.0.1 root cleaning up
      ---TRANSACTION 2990040256, ACTIVE 137 sec inserting
      mysql tables in use 1, locked 1
      LOCK WAIT 2 lock struct(s), heap size 360, 2 row lock(s)
      MySQL thread id 38773, OS thread handle 0x7f377c60e700, query id 141548 localhost root executing
      insert into reno select 500, ‘kk‘
      ------- TRX HAS BEEN WAITING 10 SEC FOR THIS LOCK TO BE GRANTED:
      RECORD LOCKS space id 64257 page no 3 n bits 80 index `PRIMARY` of table `test`.`reno` trx id 2990040256 lock_mode X insert intention waiting
      Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
      0: len 8; hex 73757072656d756d; asc supremum;;
      
      ------------------
      ---TRANSACTION 2990040255, ACTIVE 153 sec
      2 lock struct(s), heap size 360, 1 row lock(s)
      MySQL thread id 38758, OS thread handle 0x7f370807b700, query id 141432 localhost root cleaning up

      从上面的trx lock信息里看到此时等待的锁是: lock_mode X insert intention waiting

简单总结下:

  • 在case 1中, 实际上加的next-key lock是(9,9], 也就是id=9这一条记录被lock住, 其他所有的插入都没有关系.
  • 在case 2中, 因为id=15记录不存在, 且记录中上下两个边界是id=9, id=18, 因此加的next-key lock是(9, 18], 在这个区间内插入的数据都会被block, 此区间外的数据写入则不受影响.
  • 在case 3中, id=200的记录不存在, 并且比表中所有的记录都大, 因此innodb则认为next-key lock是(99, ~), 任何大于99的id记录插入都会被block, 小于99的id记录写入则不受影响.

next-key lock是为防止幻读的发生,而只有REPEATABLE-READ以及以上隔离级别才能防止幻读, 所以在READ-COMMITTED隔离级别下面没有next-key lock这一说法.

参考:

时间: 2024-08-01 16:53:35

gap lock/next-key lock浅析 Basic-Paxos协议日志同步应用的相关文章

gap lock/next-key lock浅析Basic-Paxos协议日志同步应用

http://www.cnblogs.com/renolei/p/4673842.html 当InnoDB在判断行锁是否冲突的时候, 除了最基本的IS/IX/S/X锁的冲突判断意外, InnoDB还将锁细分为如下几种子类型: record lock (RK) 记录锁, 仅仅锁住索引记录的一行 gap lock (GK) 区间锁, 仅仅锁住一个区间(开区间) insert intention lock (IK) 意向插入锁 next key lock (NK) record lock + gap

Key lock 的秘密

研究死锁,或者观察sp_lock,有时候最恼人的莫过于你看到下面研究成果的key lock,但是却不知道究竟是哪个page 哪个row被lock住了: Exec sp_lock:   就说上面的key (9dd27be994c0) 吧,能不能知道这个key,究竟是对应于那个table,那个data page,甚至哪一行(row)呢? 可以的.且听我慢慢说来. 先说这一行: 52        20        978102525      2          KEY      (9dd27b

mysql 有报错  ERROR! MySQL is not running, but lock file (/var/lock/subsys/mysql) exists

sh-4.1# /etc/init.d/mysqld status ERROR! MySQL is not running, but lock file (/var/lock/subsys/mysql) exists sh-4.1# /etc/init.d/mysqld start Starting MySQL. ERROR! The server quit without updating PID file (/data1/mysql/mysql.pid). sh-4.1# rm mysql

Multi Paxos:Basic Paxos的进化

Multi Paxos基于Basic Paxos,将原来2-Phase过程简化为了1-Phase,从而加快了提交速度.Multi Paxos要求在各个Proposer中有唯一的Leader,并由这个Leader唯一地提交value给各Acceptor进行表决,在系统中仅有一个Leader进行value提交的情况下,Prepare的过程就可以被跳过,而Leader的选举则可以由Paxos Lease来完成. 实际上,Multi Paxos并不是完全跳过了Phase-1,当系统中选举出一个新的Lea

java.util.concurrent.locks.Lock类的lock和lockInterruptibly方法的区别

什么是可中断的锁获取呢?就是:线程在等待获取锁的过程中,是否能够响应中断,以便在被中断的时候能够解除阻 塞状态,而不是傻傻地一直在等待.java对象的内置锁(synchronized)就是一种不可中断的锁,也就是说如果一个线 程在等待获取某个对象的内置锁,就算是该线程被其他线程中断,该线程仍然继续等待内置锁,而不是解除阻塞状 态,也不会抛出InterruptedException.Lock类的lock()类似synchronized,是不可中断的,在等待获取锁的过程中, 不响应中断请求:lock

lock(this)、lock(class) 、lock(object)

1. lock(this) 锁定是当前对象的实例 2.lock(class) 3.lock(object) 任意引用对象,只要是同一个引用地址都可以同步 4.lock(this) 与 lcok(class)使用 5.lock(值类型对象)   会发生自动装箱,object=new object(值类型对象),导致[锁不住],无法实现同步,故无法使用值类型对象 6.使用lock (String.Intern(str.ToString()))来同步 原文地址:https://www.cnblogs.

[MethodImpl(MethodImplOptions.Synchronized)]、lock(this)与lock(typeof(...))

对于稍微有点经验的.NET开发人员来说,倘若被问及如何保持线程同步,我想很多人都能说好好几种.在众多的线程同步的可选方式中,加锁无疑是最为常用的.如果仅仅是基于方法级别的线程同步,使用System.Runtime.CompilerServices.MethodImplAttribute无疑是最为简洁的一种方式.MethodImplAttribute可以用于instance method,也可以用于static method.当在某个方法上标注了MethodImplAttribute,并指定Met

Paxos协议基本原理

/* 版权声明:可以任意转载,转载时请标明文章原始出处和作者信息 .*/ author: 张俊林 本文节选自<大数据日知录:架构与算法>第二章"数据复制与一致性" |2.4.4 Paxos协议 在过去十年里,Paxos基本成为了分布式领域内一致性协议的代名词.Google的粗粒度锁服务Chubby的设计开发者Burrows曾经说过:"所有一致性协议本质上要么是Paxos要么是其变体".Paxos是几乎所有相关课程必讲内容以及很多其它一致性协议的起点,Pa

Paxos协议超级详细解释+简单实例

转载自:  https://blog.csdn.net/cnh294141800/article/details/53768464 Paxos协议超级详细解释+简单实例 Basic-Paxos算法(可以先看后面的实际例子再看前面的具体介绍部分) Paxos算法的目的 Paxos算法的目的是为了解决分布式环境下一致性的问题. 多个节点并发操纵数据,如何保证在读写过程中数据的一致性,并且解决方案要能适应分布式环境下的不可靠性(系统如何就一个值达到统一) Paxos的两个组件 Proposer 提议发