zoukankan      html  css  js  c++  java
  • 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索引记录前加间隙锁
  • 相关阅读:
    echarts 柱状图移除圆角
    echarts 图例显示到右边
    css图片文字一排
    linux磁盘分区、挂载、查看
    mysql的sql筛选排重最大值并修改其属性
    Java调用Linux下的shell命令并将结果以流的形式返回
    SHELL脚本中执行SQL语句操作MYSQL的5种方法
    在 Mac 上使用 `sed` 命令的几个坑
    Linux sed命令实现替换文本内容
    docker ps -a
  • 原文地址:https://www.cnblogs.com/gaogao67/p/14659081.html
Copyright © 2011-2022 走看看