• MySQL Lock--SELECT FOR UPDATE加锁


    测试环境

    • MySQL版本: 5.7.30
    • 事务级别: READ-COMMITTED

    测试内容

    在MySQL官方文档中有如下描述:

    For SELECT ... FOR UPDATE or SELECT ... LOCK IN SHARE MODE, locks are acquired for scanned rows, and expected to be released for rows that do not qualify for inclusion in the result set (for example, if they do not meet the criteria given in the WHERE clause).

    SELECT ... LOCK IN SHARE MODE sets shared next-key locks on all index records the search encounters. However, only an index record lock is required for statements that lock rows using a unique index to search for a unique row.

    SELECT ... FOR UPDATE sets an exclusive next-key lock on every record the search encounters. However, only an index record lock is required for statements that lock rows using a unique index to search for a unique row.

    For index records the search encounters, SELECT ... FOR UPDATE blocks other sessions from doing SELECT ... LOCK IN SHARE MODE or from reading in certain transaction isolation levels. Consistent reads ignore any locks set on the records that exist in the read view.

    https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-set.html

    
    ## 测试数据
    ```SQL
    mysql> show create table tb1001 G
    *************************** 1. row ***************************
           Table: tb1001
    Create Table: CREATE TABLE `tb1001` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `c1` int(11) NOT NULL,
      `c2` int(11) NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `idx_c1` (`c1`)
    ) ENGINE=InnoDB AUTO_INCREMENT=524273 DEFAULT CHARSET=utf8
    1 row in set (0.00 sec)
    
    mysql> select * from tb1001 limit 10;
    +----+----+----+
    | id | c1 | c2 |
    +----+----+----+
    |  1 |  1 |  1 |
    |  2 |  2 |  2 |
    |  3 |  3 |  3 |
    | 10 | 10 | 10 |
    | 11 | 11 | 11 |
    | 12 | 12 | 12 |
    | 13 | 13 | 13 |
    | 14 | 14 | 14 |
    | 15 | 15 | 15 |
    | 16 | 16 | 16 |
    +----+----+----+
    10 rows in set (0.00 sec)
    
    

    测试准备

    会话1执行:

    mysql> begin;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> select c1 from tb1001 where c1<10 FOR UPDATE;
    +----+
    | c1 |
    +----+
    |  1 |
    |  2 |
    |  3 |
    +----+
    3 rows in set (0.00 sec)
    
    

    查看会话1锁信息

    show engine innodb status G
    
    ---TRANSACTION 6355114, ACTIVE 28 sec
    3 lock struct(s), heap size 1136, 6 row lock(s)
    MySQL thread id 3193334, OS thread handle 140609581696768, query id 45178625 172.16.24.1 mysql_admin
    
    

    查询根据过滤条件c1<10在索引idx_c1上进行查找,对c1=[1,2,3]的索引记录加锁,产生3个row lock。

    查询再根据匹配到的索引记录在主键索引上进行查找,对id=[1,2,3]的索引记录加锁,产生3个row lock。

    测试01

    保持会话01的事务,会话02执行:

    
    mysql> begin;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> select c1 from tb1001 where c1=10 lock in share mode;
    +----+
    | c1 |
    +----+
    | 10 |
    +----+
    1 row in set (0.01 sec)
    
    mysql> select id from tb1001 where id=10 lock in share mode;
    +----+
    | id |
    +----+
    | 10 |
    +----+
    1 row in set (0.00 sec)
    
    

    查询未被阻塞,证明:

    • 会话1未在索引idx_c1的c1=10索引记录加锁
    • 会话1未在主键索引的id=10索引记录加锁

    测试02

    保持会话01的事务,会话02执行:

    
    mysql> begin;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> 
    mysql> insert into tb1001(id,c1,c2)select 9,9,9;
    Query OK, 1 row affected (0.01 sec)
    Records: 1  Duplicates: 0  Warnings: 0
    
    mysql> rollback;
    Query OK, 0 rows affected (0.01 sec)
    
    
    

    查询未被阻塞,证明:

    • 会话1未在索引idx_c1的c1=10索引记录前加间隙锁
    • 会话1未在主键索引的id=10索引记录前加间隙锁
  • 相关阅读:
    vue 使用print.js实现前端打印功能
    lin UI微信小程序组件库
    将博客搬至CSDN
    第20节:Java集合框架 【多测师_王sir】
    第19节:Java三大特性-多态之接口 【多测师_王sir】
    第18节:Java练习题 【多测师_王sir】
    第17节:Java三大特性-继承之重写 【多测师_王sir】
    第16节:Java练习题【多测师_王sir】
    第15节:Java三大特性【多测师_王sir】
    第14节:Java练习题【多测师_王sir】
  • 原文地址:https://www.cnblogs.com/gaogao67/p/14659081.html
Copyright © 2020-2023  润新知