Sql server简单锁定的例子

时间:2017-11-07 10:29:51

标签: sql sql-server express locking sql-server-2014

我以为我理解了SQL的锁定机制,但似乎我没有。我知道你可以拥有共享和独占锁,并且可以同时在同一数据上应用2个共享锁。但有人可以解释为什么查询1不会阻止查询2.我希望serializable关键字将给我一个独占锁而不是共享锁。要具体:

我创建了一个用户表:

  • id [int]
  • name [nvarchar50]

我打开用user1连接到该数据库的sql management studio并执行以下查询:

BEGIN TRAN
  select * from [user] WITH(SERIALIZABLE, TABLOCK, HOLDLOCK)
  

我故意保持交易开放。

比我打开第二个sql mangement studio用user2连接到同一个数据库并执行相同的查询。我预计第二个查询会继续运行,因为查询1在表上保持锁定,但它没有。第二个查询直接执行。为什么是这样?我的锁定提示被忽略了吗?

2 个答案:

答案 0 :(得分:1)

  1. SERIALIZABLE = HOLDLOCK制作共享锁
  2. TABLOCK指定在表级应用获取的锁。
  3. (SERIALIZABLE, TABLOCK) =表上的共享(S)锁

    如果需要使用Exclusive(X)锁定 TABLOCKX(TABLOCK,UPDLOCK)(TABLOCK,XLOCK)

答案 1 :(得分:1)

首先,on this thread很好地解释了SELECT语句无法阻止另一个语句,因为两者都只获取资源上的Shared (S)锁定,这意味着该行可用于读。阅读所有锁类型的更多here

但是,您试图通过使用Exclusive (X)提示强制select语句获取WITH(SERIALIZABLE, TABLOCK, HOLDLOCK)锁定。

这些提示"仅适用于您正在使用它的表或视图,并且仅适用于在" 中使用它们的语句定义的事务的持续时间。这在documentation中说明。

SERIALIZABLE提示通过在事务完成之前保留共享锁来限制共享锁,而不是在不再需要数据时立即释放锁。但请记住,它仍然是共享锁

为了强制执行独占锁定,您可以执行以下操作:

SELECT * 
FROM YourTable WITH (XLOCK, ROWLOCK)

SELECT resource_type, request_mode, resource_description
FROM sys.dm_tran_locks
WHERE resource_type <> 'DATABASE'

第二个查询将为您提供有关此语句中所有获取的锁的信息。 通过在某些表格中选择,我得到了以下结果:

enter image description here

请注意,我们在Intent shared (IX)PAGE本身上有一个OBJECT锁定,这是我们选择的表格,每个键上都有一个Exclusive (X)锁定