在项目中,我们经常使用到update语句,那么update语句会锁定表中的那些记录呢?此处我们通过一些简单的案例来模拟下。此处是我自己的一个理解,如果那个地方理解错了,欢迎指出
锁是加在索引上,那如果表中没有建立索引,是否就是加在表上的呢?其实不是,也是加在索引的,会存在一个默认的。
Record locks always lock index records, even if a table is defined with no indexes. For such cases, InnoDB creates a hidden clustered index and uses this index for record locking
参考链接: https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html
UPDATE ... WHERE ... sets an exclusive next-key lock on every record the search encounters
此处可以理解加锁的单位是: next-key锁
2.6.1 Record Locks
记录锁,即只会锁定一条记录。其实是锁定这条记录的索引。
A record lock is a lock on an index record. For example, SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; prevents any other transaction from inserting, updating, or deleting rows where the value of t.c1 is 10.
2.6.2 Gap Locks
间隙锁,间隙锁是在索引记录之间的间隙上的锁,即锁定一个区间。前开后开区间,不包括记录本身。
间隙锁如果是使用单列唯一索引值进行更新的话,是会退化成Record Lock。
间隙锁的目的:
Gap locking is not needed for statements that lock rows using a unique index to search > for a unique row. (This does not include the case that the search condition includes only > some columns of a multiple-column unique index; in that case, gap locking does occur.)
2.6.3 Next-Key Locks
Next-Key Lock 是索引记录上的记录锁和索引记录之前的间隙上的间隙锁的组合。也是锁定一个区间,前开后闭区间。包括记录本身。
如果索引值包括 1,5,10,30,那么next key 锁可能涵盖如下区间
negative infinity指的是负无穷。positive infinity指的是正无穷。
2.6.4 测试锁表的表结构
create table test_record_lockcreate index test_record_lock_age_index
on test_record_lock (age);
2.6.5 表中的测试数据
mysql> select * from test_record_lock;2.7 查看数据库中当前的锁
select * from performance_schema.data_locks;字段解释:
| 字段 | 值 | 解释 |
|---|---|---|
lock_type | TABLE | 锁是加在表上 |
| RECORD | 锁加在记录上 | |
lock_mode | IX | 意向排他锁 |
| X或者S | next-key lock 锁定记录本身和记录之前的间隙 | |
| X,REC_NOT_GAP | Record Lock 只锁记录自身 | |
| S,REC_NOT_GAP | Record Lock 只锁记录自身 | |
| X,GAP | gap lock | |
| X,INSERT_INTENTION | 插入意向锁 | |
lock_data | 具体的某个数字 | 表示主键的值 |
| 值,值 | 第一个值:普通索引的值 第二个值:主键值 |
疑问:X,GAP是否可以理解成X锁退化成了GAP锁。
此处适用单个字段的唯一索引,不适合多个字段的唯一索引
3.1.1 等值更新-记录存在

解释:
加next-key lock,那么锁定的记录范围为 (1,5]。
因为是唯一索引,且查询的值存在,next-key lock退化成record lock,即最终只锁定了id=5的这一行数据。其余的数据不影响。
3.1.2 等值查询-记录不存在-01

解释:
3.1.3 等值更新-记录不存在-02

3.1.4 范围更新
1、小于或等于最大临界值

此时可以发现表中扫描到的记录都加上了next key lock(锁加在索引上)
2、大于或等于最小临界值
mysql> begin;mysql> update test_record_lock set name = ‘aaa’ where id >= 1;
Query OK, 3 rows affected (0.00 sec)
Rows matched: 3Changed: 3Warnings: 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、正常范围

3.2.1 等值更新-记录存在

解释:
age加上next-key lock,锁定的范围是(10,20]3.2.2 等值更新-记录不存在

解释:
3.2.3 范围更新

解释:
普通索引的范围更新,next-key-lock不回退化成 gap lock。

从上图中可知,无索引更新数据表危险,需要谨慎处理。无索引更新,会导致全表扫描,导致将扫描到的所有记录都加上next-key lock。
1、https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html
2、https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html
到此这篇关于浅谈MySql update会锁定哪些范围的数据的文章就介绍到这了,更多相关MySql update锁定范围内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!