RC,RR隔离级别下对`select .. for update`的表现

RC,RR隔离级别下对select .. for update的表现

准备环境

mysql版本: 8.0.19 MySQL Community Server - GPL


CREATE TABLE `t` (
  `id` int NOT NULL,
  `c` int DEFAULT NULL,
  `d` int DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `c` (`c`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
insert into t values(0,0,0),(5,5,5),(10,10,10),(15,15,15),(20,20,20),(25,25,25);
mysql> select * from t;
+----+------+------+
| id | c    | d    |
+----+------+------+
|  0 |    0 |    0 |
|  5 |    5 |    5 |
| 10 |   10 |   10 |
| 15 |   15 |   15 |
| 20 |   20 |   20 |
| 25 |   25 |   25 |
+----+------+------+
6 rows in set (0.00 sec)

RC隔离级别锁住非索引列

分别开启两个session.

session1 session2
transaction_isolation =READ-COMMITTED transaction_isolation =READ-COMMITTED
begin;
select * from t where d=5 for update;
(5,5,5)
update t set d=5 where id=0;
select * from t where d=5 for update;
(0,0,5)(5,5,5)
update t set d=5 where id=0;(夯住)
update t set d=5 where id=5;(夯住)
commit;

锁的范围是d=5的行

RR隔离级别锁住非索引列

分别开启两个session:

session1 session2
begin;
select * from t where d=5 for update;
update t set d=2 where id=5(锁住);
update t set d=2 where id=0;(锁住)
/U1/update t set d=2 where id=10;(锁住){琐的类型参考下文}
insert into t values (1,1,1)锁住(INSERT_INTENTION 插入意向缩);
commit;

U1:
session1: select * from t where d=5 for update;
session2: update t set d=2 where id=10;

mysql> select * from innodb_lock_waits\G
*************************** 1. row ***************************
                wait_started: 2023-02-16 03:45:04
                    wait_age: 00:00:02
               wait_age_secs: 2
                locked_table: `sbtest`.`t`
         locked_table_schema: sbtest
           locked_table_name: t
      locked_table_partition: NULL
   locked_table_subpartition: NULL
                locked_index: PRIMARY
                 locked_type: RECORD
              waiting_trx_id: 945508
         waiting_trx_started: 2023-02-16 03:45:04
             waiting_trx_age: 00:00:02
     waiting_trx_rows_locked: 1
   waiting_trx_rows_modified: 0
                 waiting_pid: 41
               waiting_query: update t set d=2 where id=10
             waiting_lock_id: 140037579886032:188:4:4:140037475860968
           waiting_lock_mode: X,REC_NOT_GAP(行级别排它锁)
             blocking_trx_id: 945501
                blocking_pid: 40
              blocking_query: NULL
            blocking_lock_id: 140037579885160:188:4:4:140037475855096
          blocking_lock_mode: X(排它锁)
        blocking_trx_started: 2023-02-16 03:40:31
            blocking_trx_age: 00:04:35
    blocking_trx_rows_locked: 7
  blocking_trx_rows_modified: 0
     sql_kill_blocking_query: KILL QUERY 40
sql_kill_blocking_connection: KILL 40
1 row in set (0.00 sec)

锁的范围是(0,5],(5,10)

RC隔离界别锁住普通索引列

分别开启两个session:

session1 session2
transaction_isolation =READ-COMMITTED transaction_isolation =READ-COMMITTED
begin;
select * from t where c=5 for update;
update t set c=5 where id=5;(锁住)
update t set c=5 where id=0;(正常执行)
insert into t values (6,6,6);(正常执行
select * from t;
多加一行(6,6,6)
commit;
锁的范围是c=5的行

RR隔离级别锁住普通索引列

分别开启两个session:

session1 session2
begin;
select * from t where c=5 for update;
update t set c=2 where id=10;(锁住)X,GAP,INSERT_INTENTION
insert into t values (1,1,1);(锁住)X,GAP,INSERT_INTENTION
commit;

锁的范围:(0,5],(5,10)

RC隔离级别锁住主键索引列

分别开启两个session

session1 session2
transaction_isolation =READ-COMMITTED transaction_isolation =READ-COMMITTED
begin;
select * from t where id=0 for update;
update t set c=5 where id=0;(锁住)(X,REC_NOT_GAP)
insert into t values (1,1,1);
select * from t;
(0,0,0),(5,5,5),(10,10,10),(15,15,15),(20,20,20),(25,25,25),(1,1,1);
commit;
锁的范围是id=0的行

RR隔离级别锁住主键索引列

分别开启两个session

session1 session2
begin;
select * from t where id=5 for update;
update t set c=1 where id=5;(锁住)X,REC_NOT_GAP
update t set c=1 where id=0;(正常执行)
select * from t where id=0;
(0,1,0)
commit;
锁的范围是id=5的行

你可能感兴趣的:(数据库,mysql,数据库)