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索引记录前加间隙锁
  • 相关阅读:
    ASP程序调用验证码
    fcex pf.conf
    高速INTERNET代理服务器解决方案
    《IIS 6的几个经典问答》
    一个符合WEB标准的横向下拉菜单
    FREEBSD+PF 在6.2上的架设
    权限
    FreeBSD+IPFILTER实现整网(N个Vlan)透明代理上网
    pf 带宽控制 例子
    FreeBSD下配置DHCP服务小结
  • 原文地址:https://www.cnblogs.com/gaogao67/p/14659081.html
Copyright © 2011-2022 走看看