• 使用next-key locks 用于搜索和索引扫描,可以防止幻读


    Next-Key Locks
    
    A next-key lock is a combination of a record lock on the index record and a gap lock on the gap before the index 
    
    record. 
    
    是一个记录锁在索引记录上和一个区间锁在区间的组合 在index record之前
    
    
    
    InnoDB 执行行级锁以这种方式 当它搜索或者扫描一个表的索引,它设置共享或者排它锁在Index records。
    
    因此, row-level locks 实际上是 index-record locks.
    
    
    一个 next-key lock 在一个index record 也会影响 那个index record 记录前的gap
    
    
    也就是说 一个next-key lock 是一个 index-record lock plus a gap lock 
    
    
    If one session has a shared or exclusive lock on record R in an index, another session cannot insert a new index 
    
    record in the gap immediately before R in the index order. 
    
    如果一个session 有一个共享或者排它锁在记录R上,另外的session 不能插入新的index record 在before R这个区间
    
    
    Session 1:
    mysql> start transaction;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> update SmsTest set phoneNo=111 where  phoneNo <10;
    Query OK, 20 rows affected (0.01 sec)
    Rows matched: 20  Changed: 20  Warnings: 0
    
    mysql> explain  update SmsTest set phoneNo=111 where  phoneNo <10;
    +----+-------------+---------+-------+---------------+--------------+---------+-------+------
    
    +------------------------------+
    | id | select_type | table   | type  | possible_keys | key          | key_len | ref   | rows | Extra                  
    
          |
    +----+-------------+---------+-------+---------------+--------------+---------+-------+------
    
    +------------------------------+
    |  1 | SIMPLE      | SmsTest | range | SmsTest_idx1  | SmsTest_idx1 | 4       | const |   20 | Using where; Using 
    
    temporary |
    +----+-------------+---------+-------+---------------+--------------+---------+-------+------
    
    +------------------------------+
    1 row in set (0.00 sec)
    
    
    锁住1-9的记录
    
    
    mysql> select * from SmsTest  where  phoneNo <10;
    +-------+---------+-------------+--------+
    | sn    | phoneNo | channelType | status |
    +-------+---------+-------------+--------+
    |     1 |       1 |           2 |      1 |
    | 45210 |       1 |           1 |      1 |
    | 45211 |       1 |           1 |      1 |
    |     2 |       2 |           2 |      1 |
    |   201 |       2 |           1 |      1 |
    | 45212 |       2 |           1 |      1 |
    |     3 |       3 |           2 |      1 |
    | 45209 |       3 |           1 |      1 |
    | 45213 |       3 |           1 |      1 |
    |     4 |       4 |           2 |      1 |
    | 45214 |       4 |           1 |      1 |
    |     5 |       5 |           2 |      1 |
    | 45215 |       5 |           1 |      1 |
    |     6 |       6 |           2 |      1 |
    | 45216 |       6 |           1 |      1 |
    |     7 |       7 |           2 |      1 |
    | 45217 |       7 |           1 |      1 |
    |     8 |       8 |           2 |      1 |
    | 45218 |       8 |           1 |      1 |
    |     9 |       9 |           2 |      1 |
    +-------+---------+-------------+--------+
    20 rows in set (0.00 sec)
    
    
    Session 2:
    
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(1,1,1); --hang
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(2,1,1);  --hang
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(3,1,1);  --hang
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(4,1,1); --hang
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(5,1,1); --hang
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(6,1,1);  --hang
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(7,1,1); --hang
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(8,1,1); --hang
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(9,1,1); --hang
    
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(10,1,1);
    Query OK, 1 row affected (0.01 sec)
    
    mysql> 
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(11,1,1);
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(12,1,1);
    Query OK, 1 row affected (0.01 sec)
    
    
    假设一个Index 包含值10,11,13和20,可能的next-key locks 对于这个索引覆盖下面的区间,
    
    一个圆括号表示排除两端,一个方块号报表包含
    
    (negative infinity, 10] 负无穷大
    (10, 11]
    (11, 13]
    (13, 20]
    (20, positive infinity)正无穷大
    
    
    测试:
    mysql> select * from SmsTest where phoneNo in (10,11,13,20);
    +-------+---------+-------------+--------+
    | sn    | phoneNo | channelType | status |
    +-------+---------+-------------+--------+
    |    10 |      10 |           2 |      1 |
    | 45239 |      10 |           1 |      1 |
    | 45252 |      10 |           1 |      1 |
    |    11 |      11 |           2 |      1 |
    | 45253 |      11 |           1 |      1 |
    |    13 |      13 |           2 |      1 |
    |    20 |      20 |           2 |      1 |
    +-------+---------+-------------+--------+
    7 rows in set (0.00 sec)
    
    
    
    mysql> update SmsTest set phoneNo=999 where  phoneNo in (10,11,13,20);
    Query OK, 7 rows affected (0.00 sec)
    Rows matched: 7  Changed: 7  Warnings: 0
    
    mysql> explain update SmsTest set phoneNo=999 where  phoneNo in (10,11,13,20);
    +----+-------------+---------+-------+---------------+--------------+---------+-------+------
    
    +------------------------------+
    | id | select_type | table   | type  | possible_keys | key          | key_len | ref   | rows | Extra                  
    
          |
    +----+-------------+---------+-------+---------------+--------------+---------+-------+------
    
    +------------------------------+
    |  1 | SIMPLE      | SmsTest | range | SmsTest_idx1  | SmsTest_idx1 | 4       | const |    7 | Using where; Using 
    
    temporary |
    +----+-------------+---------+-------+---------------+--------------+---------+-------+------
    
    +------------------------------+
    1 row in set (0.00 sec)
    
    
    
    Session 2:
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(1,1,1);
    Query OK, 1 row affected (0.01 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(2,1,1);
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(3,1,1);
    Query OK, 1 row affected (0.05 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(4,1,1);
    Query OK, 1 row affected (0.01 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(5,1,1);
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(6,1,1);
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(7,1,1);
    Query OK, 1 row affected (0.01 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(8,1,1);
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(9,1,1); --hang
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(10,1,1);--hang
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(11,1,1); --hang
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(12,1,1); --hang
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(13,1,1);--hang
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(14,1,1);
    Query OK, 1 row affected (0.01 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(15,1,1);
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(16,1,1);
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(17,1,1);
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(18,1,1);
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(19,1,1);
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(20,1,1); --hang
    
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(21,1,1);
    Query OK, 1 row affected (0.01 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(22,1,1);
    Query OK, 1 row affected (0.00 sec)
    
    mysql>  insert into zjzc.SmsTest(PhoneNo,channelType,status)  values(23,1,1);
    Query1 row   affected (0.01 sec)
    
    默认情况下,InnoDB 操作在 REPEATABLE READ transaction isolation level  禁用innodb_locks_unsafe_for_binlog system 
    
    variable 
    
    在这种情况下,使用next-key locks 用于搜索和索引扫描,可以防止幻读

  • 相关阅读:
    IDEA+SpringMVC+Spring+Mybatis
    WSDL详解
    cxf的使用
    cxf使用wsdl文件生成代码
    给你的博客加上“Fork me on Github”彩带(转)
    老毛桃pe装机工具一键还原系统
    老毛桃pe装机工具备份系统
    java项目中classpath路径到底指的是哪里?
    this.class.getClassLoader().getResourceAsStream与this.class.getResourceAsStream
    Eclipse中导入项目后js报错解决方法(转未解决问题)
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13350135.html
Copyright © 2020-2023  润新知