原文:SQL Server Insert操作中的锁

这篇博文简单介绍一下在SQL Server中一条Insert语句中用到的锁。

准备数据

首先我们建立一张表Table_1,它有两列Id(bigint)和Value(varchar),其中Id建立了主键。

CREATE TABLE [dbo].[Table_2](
[Id] [bigint] NOT NULL,
[Value] [nchar](10) NULL,
CONSTRAINT [PK_Table_2] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

然后插入两条数据。

insert into dbo.table_2
(id, value)
values
(1, ''),
(2, '');

开始测试

我们知道,在Transaction中共享锁在查询语句结束就释放了,而排它锁则在Transaction提交才释放。我们可以利用它来执行一个Insert,不提交Transaction,然后去查看锁的状态。注意,本文中查询窗口配置的Transaction隔离级别是默认值READ COMMITTED。

首先执行以下SQL:

begin tran t1

insert into dbo.table_2
(id, value)
values
(3, '');

然后查看锁:

SELECT
resource_type,
request_mode,
resource_description,
request_session_id,
request_status,
resource_associated_entity_id,
DB_NAME(resource_database_id)as resource_database
FROM
sys.dm_tran_locks
WHERE
resource_type <> 'DATABASE'
ORDER BY
request_session_id;

执行结果如下:

  • 第一个是意向排他锁。它表示这个数据页下存在排他锁(就是第三个排他锁),我们发现它的resource_associated_entity_id和第三个锁一样。那么,这个数据页就是存放这行数据的这个主键的。
  • 第二个也是意向排他。它的resource_type是OBJECT,此对象可以是数据表、视图、存储过程、扩展存储过程或任何具有对象 ID 的对象。它的resource_associated_entity_id这一列其实是object_id, 用函数object_name(object_id)看一下发现结果是Table_2。那么它下面存在的排他锁指的也是第三个锁了。
  • 第三个是排他锁。resou_description指的是插入数据主键的哈希值。

补充1

此时,我们在另外一个命令窗口中执行以下查询语句不会产生阻塞:

SELECT *
FROM dbo.Table_2
WHERE id=1;

但另一条却会产生阻塞:

SELECT *
FROM dbo.Table_2
WHERE id=3;

来看看第一条SQL产生的锁。由于共享锁会在查询结束立即释放,因此我们加一个HOLDLOCK,让它在事务结束再释放:

begin tran t2

SELECT *
FROM dbo.Table_2 WITH(HOLDLOCK)
WHERE id=1;

这是执行完以上语句锁的情况:

第二条SQL会产生阻塞,因此可以直接查询然后看锁的情况:

我们发现第9行的resource_description和第3行是相同的,这也说明了主键的锁只是锁住了某一个值而已。

补充2

这条SQL也会被Insert阻塞:

SELECT
value
FROM
dbo.Table_2
WHERE
value=''

而且查看当前的锁可以发现,Key被锁的值正是Insert语句的Key值。这里有两个疑问:1. 为什么没用到主键列,却产生了主键锁。2.为什么Insert的数据还未commit,这里却会产生这一行主键的锁。

答:1. 我们查看查询计划,可以看到这条语句是用了聚集索引扫描,至于为什么不是表扫描,请看这里。 2. 由于事务隔离级别默认是Read Committed,所以这里会对已插入但未提交的数据主键加一个共享锁。

SQL Server Insert操作中的锁的更多相关文章

  1. (转)SQL Server 的事务和锁(一)

    SQL Server 的事务和锁(一)   最近在项目中进行压力测试遇到了数据库的死锁问题,简言之,如下的代码在 SERIALIZABLE 隔离级别造成了死锁: 1 2 3 4 5 6 7 8 9 1 ...

  2. SQL Server里的闩锁介绍

    在今天的文章里我想谈下SQL Server使用的更高级的,轻量级的同步对象:闩锁(Latch).闩锁是SQL Server存储引擎使用轻量级同步对象,用来保护多线程访问内存内结构.文章的第1部分我会介 ...

  3. SQL Server里的自旋锁介绍

    在上一篇文章里我讨论了SQL Server里的闩锁.在文章的最后我给你简单介绍了下自旋锁(Spinlock).基于那个基础,今天我会继续讨论SQL Server中的自旋锁,还有给你展示下如何对它们进行 ...

  4. SQL Server里的闩锁耦合(Latch Coupling)

    几年前,我写了篇关于闩锁和为什么SQL Server需要它们的文章.在今天的文章里,我想进一步谈下非缓存区闩锁(Non-Buffer Latches),还有在索引查找操作期间,SQL Server如何 ...

  5. (转)SQL Server 的事务和锁(二)-Range S-S锁

    在这篇随笔中,我们的主要关注点在 Key-Range Lock.Key-Range Lock有 S-S.S-U.I-N.X-X几种情况.我们一个一个来说,力求明白.遗憾的是,这里可能会比较冗长,那么死 ...

  6. SQL Server 的事务和锁(二)-Range S-S锁

    在这篇随笔中,我们的主要关注点在 Key-Range Lock.Key-Range Lock有 S-S.S-U.I-N.X-X几种情况.我们一个一个来说,力求明白.遗憾的是,这里可能会比较冗长,那么死 ...

  7. SQL Server 的事务和锁(一)

    最近在项目中进行压力测试遇到了数据库的死锁问题,简言之,如下的代码在 SERIALIZABLE 隔离级别造成了死锁: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 SELECT @ ...

  8. SQL server 2005中的锁(1)

    在之前的一片随笔中,简单的说了一下SQL Server中的隔离级别.而SQL Server的隔离级别是通过锁的机制来实现的.现在深入一下,谈谈SQL Server中的锁. 开始之前,先要定义一下前提: ...

  9. 记一次SQL Server Insert触发器编写过程

    实现功能:新增特定类型的新闻时,自动追加特定的背景图片. 第一版(错误信息:不能在 'inserted' 表和 'deleted' 表中使用 text.ntext 或 image 列),代码如下: - ...

随机推荐

  1. asp.net中通过注册表来检测是否安装Office(迅雷/QQ是否已安装)

    原文  asp.net中通过注册表来检测是否安装Office(迅雷/QQ是否已安装) 检测Office是否安装以及获取安装 路径 及安装版本  代码如下 复制代码 #region 检测Office是否 ...

  2. 实用Shell命令备忘

    开场白:这里简单记录一些常用的bash命令,一则备忘,二来希望可以帮助别人解决一些问题. 1.检测文件是否存在 if [ -f ./foo.txt ] then echo the file exist ...

  3. 《C++语言基础》实践參考——数组作数据成员

    返回:贺老师课程教学链接 [项目5 - 数组作数据成员]阅读教材P255例8.4.注意到类中的数据成员能够是数组.设计一个工资类(Salary),当中类的数据成员例如以下: class Salary ...

  4. git 提交ignore files

    1,首先在命令行创建.gitignore文件 $ touch .gitignore 2,在文件.gitignore 加入要忽略的文件入 $ echo *.class > .gitignore 3 ...

  5. [Win]进程间通信——邮槽Mailslot

    进程间通信 进程的地址空间是私有的.出于安全性的目的,如果一个进程不具有特殊的权限,是无法访问另外一个进程的内存空间的,也无法知道内存中保存的数据的意义.但是在一些具体的应用情况下需要多个进行相互配合 ...

  6. 我工作这几年(五)-- Android学习4.5月总结(一)

    今年是对我个人成长和程序员生涯冲击很大的一年. 有了小孩之后,家里发生了太多太多的事情,现在已经慢慢步入正轨,还好撑过来了,当然还有老婆.岳父岳母.我爸妈.还有好多关心支持我的人的帮助.在各种挫折交替 ...

  7. SDL Guide 中文译版

    SDL即Simple DirectMedia Layer,类似DirectX,是完整的游戏.多媒体开发包,但不同的是它跨越几乎所有的平台,有各种语言的接口,多种语言的文档,而这一切都是广大志愿者完成的 ...

  8. 在Delphi中使用C++对象(两种方法,但都要改造C++提供的DLL)

    Delphi是市场上最好的RAD工具,但是现在C++占据着主导地位,有时针对一个问题很难找到Delphi或Pascal的解决方案.可是却可能找到了一个相关的C++类.本文描述几种在Delphi代码中使 ...

  9. vs2008编译QT开源项目三国杀(五篇文章)

    请参看 http://tieba.baidu.com/f?kz=1508964881 按照上面的网址教程,下载三国杀源码,swig工具,并下载最新的QT4.8.2 for vs2008.我本机已经安装 ...

  10. navicat for mysql 如何将表ID排序重1开始?

    如果是自增字段,删除数据,他是根据原来的继续往后排的 1.你可以删除这个字段,重新建立个自增字段就可以了 2.好像也可以重新设置排序起始 alter table table_name AUTO_INC ...