由delete语句引起的锁范围扩大

阿里云月报中的一句话,出处:http://mysql.taobao.org/monthly/2022/01/01/

但是Ghost Record是可以跟正常的Record一样作为Key Range Lock的加锁对象的。可以看出这相当于把删除操作变成了更新操作,因此删除事务不再需要持有Next Key Lock

这句话意思是:假设delete语句物理删除数据,那么delete事务会持有gap lock,那么会造成锁扩大,而实际上delete操作会转为update操作,最终delete事务持有的gap lock退化为record lock,不会造成锁范围扩大

下面用SQL Server和MySQL做测试,看一下锁的情况

SQL Server 2012

use test
go


CREATE TABLE t (
id int NOT NULL primary key,
c int DEFAULT NULL,
d int DEFAULT NULL
) CREATE NONCLUSTERED INDEX [ix_t_c] ON [dbo].[t]
(
[c] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO insert into t values(5,5,5),(10,10,10),(20,20,20),(25,25,25);

使用下面的执行顺序

在session1执行下面语句

--session 1
USE test
GO SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO begin transaction select id from t where c >10 and c <= 24 delete from t where c = 25 --commit

在session2执行下面语句

--session 2
USE test
GO SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO insert into t(id,c,d) values(27,27,27); (blocked)

申请的锁,情况如下

分析:首先我们要关注的加锁对象是二级索引【ix_t_c】,可以看到有三个range锁,这里锁住的范围是

rangeS-S(10,20]

rangeX-X(20, 25]

rangeS-U[25, +∞) 正无穷

正因为rangeS-U 锁,session 2的insert操作被阻塞了,也就是删除 c=25 这行数据,导致键范围锁扩大到 正无穷


MySQL 8.0.28

set global transaction isolation level REPEATABLE READ;
select @@global.transaction_isolation; use test; CREATE TABLE `t` (
`id` int(11) NOT NULL,
`c` int(11) DEFAULT NULL,
`d` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `c` (`c`)
) ENGINE=InnoDB; insert into t values(5,5,5),(10,10,10),(20,20,20),(25,25,25);

SQL语句执行顺序跟SQL Server一样

在session1执行下面语句

-- session 1
begin;
select id from t where c >10 and c <= 24 for update;
delete from t where c = 25; --commit

在session2执行下面语句

-- session 2
insert into t(id,c,d) values(27,27,27); (blocked)

申请的锁,情况如下

select * from performance_schema.data_locks\G
*************************** 1. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552409600:1217:140111564061632
ENGINE_TRANSACTION_ID: 7643
THREAD_ID: 331
EVENT_ID: 8
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: NULL
OBJECT_INSTANCE_BEGIN: 140111564061632
LOCK_TYPE: TABLE
LOCK_MODE: IX
LOCK_STATUS: GRANTED
LOCK_DATA: NULL
*************************** 2. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552409600:59:5:1:140111564058528
ENGINE_TRANSACTION_ID: 7643
THREAD_ID: 331
EVENT_ID: 8
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: c
OBJECT_INSTANCE_BEGIN: 140111564058528
LOCK_TYPE: RECORD
LOCK_MODE: X,INSERT_INTENTION
LOCK_STATUS: WAITING
LOCK_DATA: supremum pseudo-record
*************************** 3. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552408792:1217:140111564055552
ENGINE_TRANSACTION_ID: 7642
THREAD_ID: 330
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: NULL
OBJECT_INSTANCE_BEGIN: 140111564055552
LOCK_TYPE: TABLE
LOCK_MODE: IX
LOCK_STATUS: GRANTED
LOCK_DATA: NULL
*************************** 4. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552408792:59:5:1:140111564052496
ENGINE_TRANSACTION_ID: 7642
THREAD_ID: 330
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: c
OBJECT_INSTANCE_BEGIN: 140111564052496
LOCK_TYPE: RECORD
LOCK_MODE: X
LOCK_STATUS: GRANTED
LOCK_DATA: supremum pseudo-record
*************************** 5. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552408792:59:5:4:140111564052496
ENGINE_TRANSACTION_ID: 7642
THREAD_ID: 330
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: c
OBJECT_INSTANCE_BEGIN: 140111564052496
LOCK_TYPE: RECORD
LOCK_MODE: X
LOCK_STATUS: GRANTED
LOCK_DATA: 20, 20
*************************** 6. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552408792:59:5:5:140111564052496
ENGINE_TRANSACTION_ID: 7642
THREAD_ID: 330
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: c
OBJECT_INSTANCE_BEGIN: 140111564052496
LOCK_TYPE: RECORD
LOCK_MODE: X
LOCK_STATUS: GRANTED
LOCK_DATA: 25, 25
*************************** 7. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552408792:59:4:4:140111564052840
ENGINE_TRANSACTION_ID: 7642
THREAD_ID: 330
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: PRIMARY
OBJECT_INSTANCE_BEGIN: 140111564052840
LOCK_TYPE: RECORD
LOCK_MODE: X,REC_NOT_GAP
LOCK_STATUS: GRANTED
LOCK_DATA: 20
*************************** 8. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552408792:59:4:5:140111564052840
ENGINE_TRANSACTION_ID: 7642
THREAD_ID: 330
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: PRIMARY
OBJECT_INSTANCE_BEGIN: 140111564052840
LOCK_TYPE: RECORD
LOCK_MODE: X,REC_NOT_GAP
LOCK_STATUS: GRANTED
LOCK_DATA: 25
8 rows in set (0.00 sec)

分析:这里我们要关注的加锁对象依然是二级索引【c】,这里MySQL的情况跟SQL Server一样

LOCK_MODE: X
LOCK_STATUS: GRANTED
LOCK_DATA: supremum pseudo-record

锁住的范围是 [25, +∞) 正无穷, 所以session 2的insert操作被阻塞了,也就是删除 c=25 这行数据,导致gap lock 扩大到 正无穷

通过上面两个测试,可以知道,即使delete操作在数据表中留下了Ghost Records,但是delete事务造成的gap lock范围没有缩小为Ghost Record的 record lock

因此,阿里云内核月报中的说法有失偏颇,误导读者

 

本文版权归作者所有,未经作者同意不得转载。

由delete语句引起的锁范围扩大的更多相关文章

  1. Mysql中truncate table和delete语句的区别

    Mysql中的truncate table和delete语句都可以删除表里面所有数据,但是在一些情况下有些不同! 例子: truncate table gag; (1)truncate table删除 ...

  2. MySQL-5.7 DELETE语句详解

    1.语法 (1)单表 DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name [PARTITION (partition_name [, partit ...

  3. 追踪SQL Server执行delete操作时候不同锁申请与释放的过程

    一直以为很了解sqlserver的加锁过程,在分析一些特殊情况下的死锁之后,尤其是并发单表操作发生的死锁,对于加解锁的过程,有了一些重新的认识,之前的知识还是有一些盲区在里面的.delete加锁与解锁 ...

  4. 【SQL Server学习笔记】Delete 语句、Output 子句、Merge语句

    原文:[SQL Server学习笔记]Delete 语句.Output 子句.Merge语句 DELETE语句 --建表 select * into distribution from sys.obj ...

  5. InnoDB 中不同SQL语句设置的锁

    锁定读.UPDATE 或 DELETE 通常会给在SQL语句处理过程扫描到的每个索引记录上设置记录锁.语句中是否存在排除该行的WHERE条件并不重要.InnoDB不记得确切的WHERE条件,但只知道哪 ...

  6. Sql Server系列:Delete语句

    数据的删除将删除表的部分或全部记录,删除时可以指定删除条件从而删除一条或多条记录.如果不指定删除条件,DELETE语句将删除表中全部的记录,清空数据表. 1 DELETE语法 [ WITH <c ...

  7. delete语句跑了3个小时分析以及关于并行的一些知识

    =====================START==================================== 闲来无事,看了下数据库跑的long running sql, SQL> ...

  8. SQL DELETE 语句

    DELETE 语句用于删除表中的行. 语法 DELETE FROM 表名称 WHERE 列名称 = 值 Person: LastName FirstName Address City Gates Bi ...

  9. MySQL DELETE语句和TRUNCATE TABLE语句的区别

    MySQL DELETE语句和TRUNCATE TABLE语句的区别 2010-10-08 16:05 佚名 互联网 字号:T | T 在MySQL数据库中,DELETE语句和TRUNCATE TAB ...

  10. 如何判断一条sql(update,delete)语句是否执行成功

    如何判断一条sql(update,delete)语句是否执行成功 catch  (SQLException    e)  {  }  catch不到错误应该就成功了.   ============== ...

随机推荐

  1. CSS——鼠标样式

    在浏览网页的过程中,当我们将鼠标移动到一些元素上时,鼠标的样式会发生相应的改变,例如当鼠标指向文本时,鼠标的样式会变成类似大写字母I的样子:当鼠标指向链接时,鼠标会变成一个小手的形状等. 除了这些默认 ...

  2. 【web】自定义协议Protocol URL

    URL Protocol(自定义协议)可以让web页面调用本地exe程序,这个神奇的功能是怎么实现的呢? URL ProtocolURL Protocol,没错就是标题里所说的自定义协议.这玩意儿大家 ...

  3. 莫烦tensorflow学习记录 (2)激励函数Activation Function

    https://mofanpy.com/tutorials/machine-learning/tensorflow/intro-activation-function/ 这里的 AF 就是指的激励函数 ...

  4. JavaSE 流程控制语句if while for

    目录 控制语句 if条件结构 switch语句 switch与if区别 for 循环 while循环 while与do while 控制语句 条件语句 - 根据不同条件,执行不同语句 if if... ...

  5. C#.Net筑基-String字符串超全总结 [深度好文]

    字符串是日常编码中最常用的引用类型了,可能没有之一,加上字符串的不可变性.驻留性,很容易产生性能问题,因此必须全面了解一下. 01.字符与字符编码 1.1.字符Char 字符 char 表示为 Uni ...

  6. css做多列瀑布流

    <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8 ...

  7. 算法学习笔记(45): 快速沃尔什变换 FWT

    遗憾的是 math 里面一直没有很好的讲这个东西--所以这次细致说说. FWT 的本质 类似于多项式卷积中,利用 ntt 变换使得卷积 \(\to\) 点乘,fwt 也是类似的应用. 定义某种位运算 ...

  8. OpenWrt安装配置Tailscale

    什么是tailscale? Tailscale就是基于Wireguard的一个联网工具,无需公网地址,通过去中心化,实现各个节点之间点对点的连接.配置简单友好,支持的各类平台和客户端. 相比较其他组网 ...

  9. RSS 解析:全球内容分发的利器及使用技巧

    使用 RSS 可以将最新的网络内容从一个网站分发到全球数千个其他网站. RSS 允许快速浏览新闻和更新. RSS 文档示例 <?xml version="1.0" encod ...

  10. SDL3 入门(1):Hello, SDL3!

    在本系列中我们使用 Windows Terminal + Powershell 组合作为我们在 Windows 系统下的终端工具,Windows 11 自带该环境.你也可以使用任意自己喜欢的终端环境代 ...