Code前端首页关于Code前端联系我们

MySql更新锁定哪些数据范围?

terry 2年前 (2023-09-26) 阅读数 47 #数据库

1。背景

在项目中,我们经常使用更新短语。那么update语句锁定了哪些表记录呢?这里我们通过一些简单的案例来模拟一下。 这是我自己的看法。如果理解有误,请指出。

2。所需信息

2.1 数据库隔离级别

mysql> show variables like 'transaction_isolation';
+-----------------------+-----------------+
| Variable_name         | Value           |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.00 sec)

2.2 数据库版本

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.28    |
+-----------+
1 row in set (0.00 sec)

2.3 数据库存储引擎

mysql> show variables like '%storage_engine%';
+---------------------------------+-----------+
| Variable_name                   | Value     |
+---------------------------------+-----------+
| default_storage_engine          | InnoDB    |
| default_tmp_storage_engine      | InnoDB    |
| disabled_storage_engines        |           |
| internal_tmp_mem_storage_engine | TempTable |
+---------------------------------+-----------+
4 rows in set (0.01 sec)

2.4 是否对记录或索引添加了锁? 到索引中,那么如果表上没有创建索引,是否会添加到表中呢?其实不是,它也被添加到目录中并且有一个默认值。

记录锁始终锁定索引记录,即使表定义为没有索引。在这种情况下,InnoDB会创建一个隐藏的聚集索引,并使用该索引来锁定记录

参考链接:https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-intention -locks

2.5 update...其中锁定的基本单位是

UPDATE ... WHERE ... 对搜索遇到的每条记录设置独占的 next key 锁
这里可以理解为锁定的单位是:下一个键

2.6行级锁

2.6.1记录锁

仅存储一个,编辑。它实际上锁定了该记录的索引。
记录锁是目录记录锁。例如 SELECT c1 FROM t WHERE c1 = 10 UPDATE;防止其他事务添加、更新或删除 t.c1 值为 10 的行。

2.6.2 间隙锁

间隙锁,间隙锁是记录中目录之间的间隙,即锁定间隙。 开合前后开合间隔,不包括盘本身。如果使用 一列的唯一索引值 更新

间隙锁定 ,则 会锁定 。 。

光圈锁定目的

  1. 防止向间隙添加新数据
  2. 防止现有数据更新到间隙。

使用唯一索引锁定行来查找唯一行的语句不需要间隙锁定。 (此不包括情况,其中搜索条件仅包含多列唯一索引中的一些列;在这种情况下会发生间隙锁定。)❙❙❀。 .3 下一键锁

下一键锁位于

索引记录中。 记录锁定 和间隙锁定 的组合,在 索引记录之前有间隙。它还锁定间隙, 从前面打开并在 之间闭合。包括光盘本身。

如果索引值包含1,5,10,30,则下一个键锁可以跨越下一个区间

(negative infinity, 1]
(1, 115
(5, 10]
(10, 30]
(30, positive infinity)

到负无穷大❀到负无穷大。 正无穷大指的是正无穷大。

2.6.4 测试锁表的表结构

create table test_record_lock
(
    id   int         not null comment '主键',
    age  int         null comment '年龄,普通索引',
    name varchar(10) null comment '姓名,无索引',
    constraint test_record_lock_pk
        primary key (id)
)
    comment '测试记录锁';

create index test_record_lock_age_index
    on test_record_lock (age);

2.6.5 测试表中的数据

mysql> select * from test_record_lock;
+----+------+--------+
| id | age  | name   |
+----+------+--------+
|  1 |   10 | 张三   |
|  5 |   20 | 李四   |
|  8 |   25 | 王五   |
+----+------+--------+
3 rows in set (0.00 sec)

2.7 查看数据库当前的锁

selectda_performance;说明:

字段说明
lock_typeTABLECLock锁定已添加到记录中
锁定模式 IX目的锁定
X或S下一个键锁定
锁定记录本身以及记录之前的间隙
AP
X,REC_NOT锁定记录本身
S,REC_NOT_GAP 记录锁定只锁定记录本身
X,GAP开锁
表示主键值❙值:常规索引的值
第二个值:主键值

问题:X,GAP能否理解XGAP锁。 ? 说明:

  1. 加上下一个key的锁,则锁定的记录范围为(1,5)。
  2. 由于是唯一索引,且查询值存在,所以下一个key的锁就变成了一条记录lock,即只锁定id=5的数据行,其他信息不受影响
    3.1.2对应的查询记录不存在 -01

    MySql update会锁定哪些范围的数据?

说明:

  1. 添加下一条key lock ,锁定的记录范围是(5,8)。
  2. 因为是唯一索引,请求的值不存在,所以下一个key的锁定就变成了gap,即最终锁定的数据范围是( 5,8) 其他数据不受影响。
3.1.3 对应更新-记录不存在-02

MySql update会锁定哪些范围的数据?

3.1.4 区域更新
1.小于等于最大临界值

MySql update会锁定哪些范围的数据?

此时可以发现表中扫描到的所有记录都已添加。下一个键锁(该锁添加到索引中)

2,大于等于最小临界值
mysql> begin;
Query OK, 0 rows affected (0.01 sec)

mysql> update test_record_lock set name = 'aaa' where id >= 1;
Query OK, 3 rows affected (0.00 sec)
Rows matched: 3  Changed: 3  Warnings: 0

mysql> select LOCK_TYPE,INDEX_NAME,LOCK_MODE,LOCK_DATA from performance_schema.data_locks;
+-----------+------------+---------------+------------------------+
| LOCK_TYPE | INDEX_NAME | LOCK_MODE     | LOCK_DATA              |
+-----------+------------+---------------+------------------------+
| TABLE     | NULL       | IX            | NULL                   |
| RECORD    | PRIMARY    | X,REC_NOT_GAP | 1                      |
| RECORD    | PRIMARY    | X             | supremum pseudo-record |
| RECORD    | PRIMARY    | X             | 8                      |
| RECORD    | PRIMARY    | X             | 5                      |
+-----------+------------+---------------+------------------------+
5 rows in set (0.01 sec)

目前只能将小于最小临界值的记录添加到表中。 ,正常范围正 3.2 正常指标测试

3.2.1 对应更新记录是否存在

MySql update会锁定哪些范围的数据?

说明:先到常规目录AGE加Next-Key锁定,锁定范围为(10,20]

  • next键也锁定了这条记录,所以添加了Record Lock id索引值等于5
  • 由于是普通索引且该值仍然存在,因此对该记录中的下一个间隙添加Gap Lock并锁定范围为 (20,25)
  • 3.2.2 对应更新 - 记录不存在

    MySql update会锁定哪些范围的数据?

    说明:

    1. 获取下一键的锁定 锁定范围为 (10,20]
    2. 因为记录不需要更新,下一个key的锁变成区间锁,所以锁定的范围是(10,20)
    3. 因为是普通索引,记录不存在,所以不需要更新再次搜索下一个区间。
    3.2.3 范围更新

    MySql update会锁定哪些范围的数据?

    说明:

    1. 平常的索引范围更新,下一个key lock不会变为gap lock。
    3.3 无索引更新

    MySql update会锁定哪些范围的数据?

    如上图所示,在没有索引的情况下更新数据表是危险的,需谨慎处理。没有索引更新会导致全表扫描,添加所有扫描记录next-key lock

    3.参考链接

    1。 https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-intention-locks
    2,https://dev.mysql.com/doc/refman/8.0/ fi/innodb-locking.html

    版权声明

    本文仅代表作者观点,不代表Code前端网立场。
    本文系作者Code前端网发表,如需转载,请注明页面地址。

    发表评论:

    ◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

    热门