Sql server 第一个事务完成后,第二个事务仍在等待

Sql server 第一个事务完成后,第二个事务仍在等待,sql-server,tsql,transactions,locks,Sql Server,Tsql,Transactions,Locks,在SSMS中的两个窗口中逐个运行相同的脚本,延迟几秒钟。 稍后启动的第二个实例将完成,但第一个实例将保持锁定状态,直到关闭第二个窗口。 这里发生了什么?为什么在提交后不释放锁 SET TRAN ISOLATION LEVEL SERIALIZABLE BEGIN TRAN SELECT * FROM dbo.t1 WHERE id IN (1,3) WAITFOR DELAY '00:00:20' UPDATE t1 SET InUse=0 WHERE id IN (1,3) COMMI

在SSMS中的两个窗口中逐个运行相同的脚本,延迟几秒钟。
稍后启动的第二个实例将完成,但第一个实例将保持锁定状态,直到关闭第二个窗口。 这里发生了什么?为什么在提交后不释放锁

SET TRAN ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN

SELECT * FROM dbo.t1
WHERE id IN (1,3)

WAITFOR DELAY '00:00:20'

UPDATE t1 SET InUse=0
WHERE id IN (1,3)

COMMIT
编辑:

表格结构如下:

CREATE TABLE [dbo].[t1](
    [id] [INT] NOT NULL,
    [InUse] [BIT] NOT NULL DEFAULT ((0)),
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]

你应该用表格结构更新你的问题

由于您没有指定表上是否有任何索引,我假设没有,即
dbo.t1
是一个

在这种情况下,您将得到经典的死锁:

session1
希望从表中选择
并需要
S
用于它读取的任何行,并且由于
dbo.t1上没有
索引
,因此整个表被读取,并且在整个事务期间保持表上的
S-lock

同时,
session2
也执行同样的操作,它还获取表上的
S-lock
,并将其保存

Session1
现在需要将其
S-lock
转换为
IX
,以便执行
更新
,它被
session2
阻止,该会话在
dbo.t1
上保持
S

session2
尝试执行相同操作时,会导致死锁,因为两个会话都需要
IX
,并且都被其他会话锁定

下面是相应的死锁图:

deadlock-list
 deadlock victim=process155d1d498
  process-list
   process id=process155d1d498 taskpriority=0 logused=0 waitresource=OBJECT: 26:1765581328:0  waittime=16222 ownerId=5528849 transactionname=user_transaction lasttranstarted=2019-02-07T13:39:38.837 XDES=0x15ec1c3a8 lockMode=IX schedulerid=4 kpid=8140 status=suspended spid=54 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2019-02-07T13:39:38.833 lastbatchcompleted=2019-02-07T13:39:38.833 lastattention=2019-02-07T13:38:49.187 clientapp=Microsoft SQL Server Management Studio - Query hostname=pppp hostpid=12276 loginname=FINCONSGROUP\anna.savchenko isolationlevel=serializable (4) xactid=5528849 currentdb=26 lockTimeout=4294967295 clientoption1=671098976 clientoption2=390200
    executionStack
     frame procname=adhoc line=9 stmtstart=248 stmtend=334 sqlhandle=0x02000000f445021276fec0f5ec119082f65611ce316a4d280000000000000000000000000000000000000000
UPDATE t1 SET InUse=0
WHERE id IN (1,3)     
    inputbuf
SET TRAN ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
SELECT * FROM dbo.t1
WHERE id IN (1,3)
WAITFOR DELAY '00:00:20'
UPDATE t1 SET InUse=0
WHERE id IN (1,3)
COMMIT
   process id=process15649f868 taskpriority=0 logused=0 waitresource=OBJECT: 26:1765581328:0  waittime=1212 ownerId=5529084 transactionname=user_transaction lasttranstarted=2019-02-07T13:39:53.847 XDES=0x15ec1d048 lockMode=IX schedulerid=3 kpid=15516 status=suspended spid=57 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2019-02-07T13:39:53.847 lastbatchcompleted=2019-02-07T13:39:53.847 lastattention=1900-01-01T00:00:00.847 clientapp=Microsoft SQL Server Management Studio - Query hostname=pppp hostpid=12276 loginname=FINCONSGROUP\anna.savchenko isolationlevel=serializable (4) xactid=5529084 currentdb=26 lockTimeout=4294967295 clientoption1=671098976 clientoption2=390200
    executionStack
     frame procname=adhoc line=9 stmtstart=248 stmtend=334 sqlhandle=0x0200000093b3ba1c08d586d1f142f473a7c8996074a369fc0000000000000000000000000000000000000000
UPDATE t1 SET InUse=0
WHERE id IN (1,3)     
    inputbuf
SET TRAN ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
SELECT * FROM dbo.t1
WHERE id IN (1,3)
WAITFOR DELAY '00:00:20'
UPDATE t1 SET InUse=0
WHERE id IN (1,3)
COMMIT    
  resource-list
   objectlock lockPartition=0 objid=1765581328 subresource=FULL dbid=26 objectname=parts.dbo.t1 id=lock152c2d300 mode=S associatedObjectId=1765581328
    owner-list
     owner id=process15649f868 mode=S
     owner id=process15649f868 mode=IX requestType=convert
    waiter-list
     waiter id=process155d1d498 mode=IX requestType=convert
   objectlock lockPartition=0 objid=1765581328 subresource=FULL dbid=26 objectname=parts.dbo.t1 id=lock152c2d300 mode=S associatedObjectId=1765581328
    owner-list
     owner id=process155d1d498 mode=S
     owner id=process155d1d498 mode=IX requestType=convert
    waiter-list
     waiter id=process15649f868 mode=IX requestType=convert

你应该用表格结构更新你的问题

由于您没有指定表上是否有任何索引,我假设没有,即
dbo.t1
是一个

在这种情况下,您将得到经典的死锁:

session1
希望从表中选择
并需要
S
用于它读取的任何行,并且由于
dbo.t1上没有
索引
,因此整个表被读取,并且在整个事务期间保持表上的
S-lock

同时,
session2
也执行同样的操作,它还获取表上的
S-lock
,并将其保存

Session1
现在需要将其
S-lock
转换为
IX
,以便执行
更新
,它被
session2
阻止,该会话在
dbo.t1
上保持
S

session2
尝试执行相同操作时,会导致死锁,因为两个会话都需要
IX
,并且都被其他会话锁定

下面是相应的死锁图:

deadlock-list
 deadlock victim=process155d1d498
  process-list
   process id=process155d1d498 taskpriority=0 logused=0 waitresource=OBJECT: 26:1765581328:0  waittime=16222 ownerId=5528849 transactionname=user_transaction lasttranstarted=2019-02-07T13:39:38.837 XDES=0x15ec1c3a8 lockMode=IX schedulerid=4 kpid=8140 status=suspended spid=54 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2019-02-07T13:39:38.833 lastbatchcompleted=2019-02-07T13:39:38.833 lastattention=2019-02-07T13:38:49.187 clientapp=Microsoft SQL Server Management Studio - Query hostname=pppp hostpid=12276 loginname=FINCONSGROUP\anna.savchenko isolationlevel=serializable (4) xactid=5528849 currentdb=26 lockTimeout=4294967295 clientoption1=671098976 clientoption2=390200
    executionStack
     frame procname=adhoc line=9 stmtstart=248 stmtend=334 sqlhandle=0x02000000f445021276fec0f5ec119082f65611ce316a4d280000000000000000000000000000000000000000
UPDATE t1 SET InUse=0
WHERE id IN (1,3)     
    inputbuf
SET TRAN ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
SELECT * FROM dbo.t1
WHERE id IN (1,3)
WAITFOR DELAY '00:00:20'
UPDATE t1 SET InUse=0
WHERE id IN (1,3)
COMMIT
   process id=process15649f868 taskpriority=0 logused=0 waitresource=OBJECT: 26:1765581328:0  waittime=1212 ownerId=5529084 transactionname=user_transaction lasttranstarted=2019-02-07T13:39:53.847 XDES=0x15ec1d048 lockMode=IX schedulerid=3 kpid=15516 status=suspended spid=57 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2019-02-07T13:39:53.847 lastbatchcompleted=2019-02-07T13:39:53.847 lastattention=1900-01-01T00:00:00.847 clientapp=Microsoft SQL Server Management Studio - Query hostname=pppp hostpid=12276 loginname=FINCONSGROUP\anna.savchenko isolationlevel=serializable (4) xactid=5529084 currentdb=26 lockTimeout=4294967295 clientoption1=671098976 clientoption2=390200
    executionStack
     frame procname=adhoc line=9 stmtstart=248 stmtend=334 sqlhandle=0x0200000093b3ba1c08d586d1f142f473a7c8996074a369fc0000000000000000000000000000000000000000
UPDATE t1 SET InUse=0
WHERE id IN (1,3)     
    inputbuf
SET TRAN ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
SELECT * FROM dbo.t1
WHERE id IN (1,3)
WAITFOR DELAY '00:00:20'
UPDATE t1 SET InUse=0
WHERE id IN (1,3)
COMMIT    
  resource-list
   objectlock lockPartition=0 objid=1765581328 subresource=FULL dbid=26 objectname=parts.dbo.t1 id=lock152c2d300 mode=S associatedObjectId=1765581328
    owner-list
     owner id=process15649f868 mode=S
     owner id=process15649f868 mode=IX requestType=convert
    waiter-list
     waiter id=process155d1d498 mode=IX requestType=convert
   objectlock lockPartition=0 objid=1765581328 subresource=FULL dbid=26 objectname=parts.dbo.t1 id=lock152c2d300 mode=S associatedObjectId=1765581328
    owner-list
     owner id=process155d1d498 mode=S
     owner id=process155d1d498 mode=IX requestType=convert
    waiter-list
     waiter id=process15649f868 mode=IX requestType=convert

在2个不同会话上运行脚本时,我得到了预期的死锁错误。我的猜测是,第二个会话已经有一个打开的事务,因此它实际上没有提交(只是减少事务计数),阻塞第一个会话,直到第二个会话关闭并回滚。如果@TRANCOUNT>0回滚,请尝试添加
到脚本的开头。谢谢!我第一次遇到dedlock失败,但在subqent运行时,第一个事务一直在等待。现在我可以始终如一地重现死锁。当我在两个不同的会话上运行脚本时,我得到了预期的死锁错误。我的猜测是,第二个会话已经有一个打开的事务,因此它实际上没有提交(只是减少事务计数),阻塞第一个会话,直到第二个会话关闭并回滚。如果@TRANCOUNT>0回滚,请尝试添加
到脚本的开头。谢谢!我第一次遇到dedlock失败,但在subqent运行时,第一个事务一直在等待。现在,我可以始终如一地重现僵局。