了解导致死锁的锁定行为
Understanding locking behavior causing deadlock
我目前正在调查一个频繁使用的数据库的死锁问题,但即使使用并发 ostress 会话或 WHILE 1=1 EXEC StoredProcs 仍然无法重现它。我真的很高兴有人能阐明重现它的方法并帮助我理解它的行为。
涉及两个 table,它们根据原始 PK 通过计算列中的散列进行分区。由于过去 INSERT 上的页面闩锁问题,它们被分区。
多亏了这个好方法 article(发现在多次执行此操作时更容易 - 不必发出 SELECT 和 DBCC PAGE),在尝试重现该场景时,我发现表明 INSERT 语句获取了以下锁:
- Obj-IS 在 tConn
- Obj-IX 在 tVarConn
- Page-IX 来自 tVarConn 的页面
- Key-RI_NL 从 tVarConn
到下一个 %%lockres%%
- Key-X 在被插入行的 %%lockres%% 上
- Page-IS 来自 tConn 的页面
- Key-S 来自 tConn
的 parent 键值的 %%lockres%%
删除的是:
- Obj-IX 在 tVarConn
- Page-IX 在 tVarConn
- Key-X 在 tVarConn 上(其中几个具有不同的 %%lockres%% 因为我有多个行用于 nConn/HashID 对)
计划:
Insert Plan
Delete Plan
死锁图:
deadlock-list
deadlock victim=process48094508
process-list
process id=process48094508 taskpriority=0 logused=428 waitresource=KEY: 10:72057666620227584 (d79f02e56828) waittime=2832 ownerId=28655562221 transactionname=implicit_transaction lasttranstarted=2020-04-19T09:37:13.823 XDES=0x7d33ef970 lockMode=X schedulerid=15 kpid=22212 status=suspended spid=2684 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2020-04-19T09:37:13.857 lastbatchcompleted=2020-04-19T09:37:13.857 clientapp=websphere1 hostname=wsserver1 hostpid=0 loginname=dblogin isolationlevel=repeatable read (3) xactid=28655562221 currentdb=10 lockTimeout=4294967295 clientoption1=673185824 clientoption2=128058
executionStack
frame procname=MYDB.dbo.pInsVarConn line=14 stmtstart=470 stmtend=690 sqlhandle=0x03000b00a3f2cc6277eb2bc0b8a900000100000000000000
INSERT INTO tVarConn (nConn, iVarConn, rVarConn)
VALUES (@nConn, @iVarConn, @rVarConn)
frame procname=MYDB.dbo.pPrcInsVarConnao01 line=66 stmtstart=4890 stmtend=5016 sqlhandle=0x03000a004c202f3094703d009e1b00000100000000000000
EXEC dbo.pInsVarConn @nConn, @iVarConn, @rVarConn
frame procname=adhoc line=1 stmtstart=96 sqlhandle=0x01000a00b3117f0a40e2b01b0f0000000000000000000000
EXEC pPrcInsVarConnao01 @P0,@P1,@P2
inputbuf
(@P0 bigint,@P1 varchar(8000),@P2 varchar(8000))EXEC pPrcInsVarConnao01 @P0,@P1,@P2
process id=process48153948 taskpriority=0 logused=11224 waitresource=KEY: 10:72057666620227584 (0a7b9247f732) waittime=2832 ownerId=28655563535 transactionname=DELETE lasttranstarted=2020-04-19T09:37:13.857 XDES=0x2760ee83b0 lockMode=X schedulerid=34 kpid=31228 status=suspended spid=2553 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2020-04-19T09:37:13.857 lastbatchcompleted=2020-04-19T09:37:13.263 clientapp=websphere1 hostname=wsserver1 hostpid=0 loginname=dblogin isolationlevel=repeatable read (3) xactid=28655563535 currentdb=10 lockTimeout=4294967295 clientoption1=673185824 clientoption2=128056
executionStack
frame procname=MYDB.dbo.pPrcEndConnao02 line=54 stmtstart=2480 stmtend=2666 sqlhandle=0x03000a00d95fa90184eb2b00b8aa00000100000000000000
DELETE FROM dbo.tVarConn WHERE nConn = @IdConnao AND HashID = @HashID
frame procname=adhoc line=1 stmtstart=132 sqlhandle=0x01000a00a7b5550840229a10010d00000000000000000000
exec pPrcEndConnao02 @P0,@P1,@P2,@P3
frame procname=unknown line=1 sqlhandle=0x000000000000000000000000000000000000000000000000
unknown
inputbuf
(@P0 bigint,@P1 varchar(8000),@P2 varchar(8000),@P3 varchar(8000))exec pPrcEndConnao02 @P0,@P1,@P2,@P3
resource-list
keylock hobtid=72057666620227584 dbid=10 objectname=MYDB.dbo.tVarConn indexname=PKtVarConn id=lock495af880 mode=X associatedObjectId=72057666620227584
owner-list
owner id=process48153948 mode=X
waiter-list
waiter id=process48094508 mode=X requestType=wait
keylock hobtid=72057666620227584 dbid=10 objectname=MYDB.dbo.tVarConn indexname=PKtVarConn id=lock1d7ff99b80 mode=X associatedObjectId=72057666620227584
owner-list
owner id=process48094508 mode=X
waiter-list
waiter id=process48153948 mode=X requestType=wait
我错过了什么?这两个怎么会卷入上面的僵局呢?我如何重现它以便测试可能的解决方案?
抱歉,如果这太长了或者我错过了什么...第一次发帖! :)
环境
Parent table:
Name Owner Type
--------- -------- -------------
tConn dbo user table
Column_name Type Computed Length Prec Scale Nullable TrimTrailingBlanks FixedLenNullInSource Collation
-------------- ----------- ----------- --------- ----- ----- ----------- ---------------------- ------------------------- ----------------------------
nConn int no 4 10 0 no (n/a) (n/a) NULL
Col1 smallint no 2 5 0 no (n/a) (n/a) NULL
Col2 char no 23 no no no SQL_Latin1_General_CP1_CI_AI
Col3 datetime no 8 no (n/a) (n/a) NULL
Col4 char no 20 no no no SQL_Latin1_General_CP1_CI_AI
Col5 datetime no 8 no (n/a) (n/a) NULL
Col6 varchar no 50 yes no yes SQL_Latin1_General_CP1_CI_AI
Col7 char no 1 no no no SQL_Latin1_General_CP1_CI_AI
Col8 smallint no 2 5 0 no (n/a) (n/a) NULL
Col9 smallint no 2 5 0 no (n/a) (n/a) NULL
Col10 smallint no 2 5 0 no (n/a) (n/a) NULL
Col11 decimal no 9 10 0 no (n/a) (n/a) NULL
Col12 decimal no 5 5 0 yes (n/a) (n/a) NULL
HashID tinyint yes 1 3 0 no (n/a) (n/a) NULL
Identity Seed Increment Not For Replication
----------- ------ ----------- -------------------
nConn 1 1 0
index_name index_description index_keys
------------- ------------------------------------------------------ -----------------
Idx1tConn nonclustered located on schPartConn Col2
Idx2tConn nonclustered located on schPartConn Col1, Col4, Col7
PKtConn clustered, unique, primary key located on schPartConn HashID, nConn
constraint_type constraint_name delete_action update_action status_enabled status_for_replication constraint_keys
-------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------- ------------- ------------- -------------- ---------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
FOREIGN KEY FktAplic01 No Action No Action Enabled Is_For_Replication Col1
REFERENCES MYDB.dbo.tAplic (Col1)
PRIMARY KEY (clustered) PKtConn (n/a) (n/a) (n/a) (n/a) HashID, nConn
Table is referenced by foreign key
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MYDB.dbo.tVarConn: FktConn01
这是child table:
Name Owner Type
---------- ------- -----------
tVarConn dbo user table
Column_name Type Computed Length Prec Scale Nullable TrimTrailingBlanks FixedLenNullInSource Collation
-------------- ---------- ----------- -------- ----- ----- ----------- --------------------- ---------------------- -----------------------------
nConn int no 4 10 0 no (n/a) (n/a) NULL
iVarConn char no 20 no no no SQL_Latin1_General_CP1_CI_AI
rVarConn varchar no 8000 no no no SQL_Latin1_General_CP1_CI_AI
HashID tinyint yes 1 3 0 no (n/a) (n/a) NULL
index_name index_description index_keys
--------------- -------------------------------------------------------- ------------------------
PKtVarConn clustered, unique, primary key located on schPartConn HashID, nConn, iVarConn
constraint_type constraint_name delete_action update_action status_enabled status_for_replication constraint_keys
------------------------ ------------------ ------------- ------------- -------------- ---------------------- ----------------
FOREIGN KEY FktConn01 Cascade No Action Enabled Is_For_Replication HashID, nConn
REFERENCES MYDB.dbo.tConn (HashID, nConn)
PRIMARY KEY (clustered) PKtVarConn (n/a) (n/a) (n/a) (n/a) HashID, nConn, iVarConn
No foreign keys reference table 'tVarConn', or you do not have permissions on referencing tables.
存储过程:
CREATE PROCEDURE [dbo].[pInsVarConn] (
@nConn int,
@iVarConn char(20),
@rVarConn varchar(8000)
)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO tVarConn (nConn, iVarConn, rVarConn)
VALUES (@nConn, @iVarConn, @rVarConn)
END
go
CREATE PROCEDURE [dbo].[pPrcInsVarConnao01] (
@nConn int,
@iVarConn char(20),
@rVarConn varchar(8000)
)
AS
BEGIN
SET NOCOUNT ON
DECLARE @HashID tinyint
SET @HashID =CONVERT([tinyint],abs(@nConn%(72)),(0))
IF EXISTS(SELECT TOP 1 1 FROM tVarConn WITH(NOLOCK) WHERE nConn = @nConn AND HashID = @HashID AND iVarConn = @iVarConn)
BEGIN
exec [pUpdtVarConn] @nConn, @iVarConn, @rVarConn
END
ELSE
BEGIN
exec [pInsVarConn] @nConn, @iVarConn, @rVarConn
END
END
go
CREATE PROCEDURE [dbo].[pPrcEndConnao02](
@IdConnao int,
@SeqGen char(23),
@CurrEnd char(50),
@Valid char(1) = 'N'
)
AS
DECLARE @HashID tinyint
DECLARE @EndUs char(50)
DECLARE @StConnao char(1)
DECLARE @RC smallint
BEGIN
SET NOCOUNT ON
SET @HashID =CONVERT([tinyint],abs(@IdConnao%(72)),(0))
SELECT
@EndUs = Col6,
@StConnao = Col7
FROM
dbo.tConn WITH(NOLOCK)
WHERE
nConn = @IdConnao AND
HashID = @HashID AND
Col2 = @SeqGen
IF(@@ROWCOUNT = 0)
BEGIN
SET @RC = -5014
END
ELSE
BEGIN
IF(@stConnao = 'F')
BEGIN
SET @RC = -5012
END
ELSE
BEGIN
UPDATE dbo.tConn
SET Col7 = 'F'
WHERE nConn = @IdConnao
AND HashID = @HashID
AND Col2 = @SeqGen
DELETE FROM dbo.tVarConn WHERE nConn = @IdConnao AND HashID = @HashID
SET @RC = 0
END
END
SELECT @RC AS Ret
END
非常感谢!
英尺
发现 java 应用程序打开的外部事务中有资源被锁定,该应用程序禁用了 运行 几个存储过程的自动提交设置,然后提交。
这解释了 trancount=2。
英尺
我目前正在调查一个频繁使用的数据库的死锁问题,但即使使用并发 ostress 会话或 WHILE 1=1 EXEC StoredProcs 仍然无法重现它。我真的很高兴有人能阐明重现它的方法并帮助我理解它的行为。
涉及两个 table,它们根据原始 PK 通过计算列中的散列进行分区。由于过去 INSERT 上的页面闩锁问题,它们被分区。
多亏了这个好方法 article(发现在多次执行此操作时更容易 - 不必发出 SELECT 和 DBCC PAGE),在尝试重现该场景时,我发现表明 INSERT 语句获取了以下锁:
- Obj-IS 在 tConn
- Obj-IX 在 tVarConn
- Page-IX 来自 tVarConn 的页面
- Key-RI_NL 从 tVarConn 到下一个 %%lockres%%
- Key-X 在被插入行的 %%lockres%% 上
- Page-IS 来自 tConn 的页面
- Key-S 来自 tConn 的 parent 键值的 %%lockres%%
删除的是:
- Obj-IX 在 tVarConn
- Page-IX 在 tVarConn
- Key-X 在 tVarConn 上(其中几个具有不同的 %%lockres%% 因为我有多个行用于 nConn/HashID 对)
计划: Insert Plan Delete Plan
死锁图:
deadlock-list
deadlock victim=process48094508
process-list
process id=process48094508 taskpriority=0 logused=428 waitresource=KEY: 10:72057666620227584 (d79f02e56828) waittime=2832 ownerId=28655562221 transactionname=implicit_transaction lasttranstarted=2020-04-19T09:37:13.823 XDES=0x7d33ef970 lockMode=X schedulerid=15 kpid=22212 status=suspended spid=2684 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2020-04-19T09:37:13.857 lastbatchcompleted=2020-04-19T09:37:13.857 clientapp=websphere1 hostname=wsserver1 hostpid=0 loginname=dblogin isolationlevel=repeatable read (3) xactid=28655562221 currentdb=10 lockTimeout=4294967295 clientoption1=673185824 clientoption2=128058
executionStack
frame procname=MYDB.dbo.pInsVarConn line=14 stmtstart=470 stmtend=690 sqlhandle=0x03000b00a3f2cc6277eb2bc0b8a900000100000000000000
INSERT INTO tVarConn (nConn, iVarConn, rVarConn)
VALUES (@nConn, @iVarConn, @rVarConn)
frame procname=MYDB.dbo.pPrcInsVarConnao01 line=66 stmtstart=4890 stmtend=5016 sqlhandle=0x03000a004c202f3094703d009e1b00000100000000000000
EXEC dbo.pInsVarConn @nConn, @iVarConn, @rVarConn
frame procname=adhoc line=1 stmtstart=96 sqlhandle=0x01000a00b3117f0a40e2b01b0f0000000000000000000000
EXEC pPrcInsVarConnao01 @P0,@P1,@P2
inputbuf
(@P0 bigint,@P1 varchar(8000),@P2 varchar(8000))EXEC pPrcInsVarConnao01 @P0,@P1,@P2
process id=process48153948 taskpriority=0 logused=11224 waitresource=KEY: 10:72057666620227584 (0a7b9247f732) waittime=2832 ownerId=28655563535 transactionname=DELETE lasttranstarted=2020-04-19T09:37:13.857 XDES=0x2760ee83b0 lockMode=X schedulerid=34 kpid=31228 status=suspended spid=2553 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2020-04-19T09:37:13.857 lastbatchcompleted=2020-04-19T09:37:13.263 clientapp=websphere1 hostname=wsserver1 hostpid=0 loginname=dblogin isolationlevel=repeatable read (3) xactid=28655563535 currentdb=10 lockTimeout=4294967295 clientoption1=673185824 clientoption2=128056
executionStack
frame procname=MYDB.dbo.pPrcEndConnao02 line=54 stmtstart=2480 stmtend=2666 sqlhandle=0x03000a00d95fa90184eb2b00b8aa00000100000000000000
DELETE FROM dbo.tVarConn WHERE nConn = @IdConnao AND HashID = @HashID
frame procname=adhoc line=1 stmtstart=132 sqlhandle=0x01000a00a7b5550840229a10010d00000000000000000000
exec pPrcEndConnao02 @P0,@P1,@P2,@P3
frame procname=unknown line=1 sqlhandle=0x000000000000000000000000000000000000000000000000
unknown
inputbuf
(@P0 bigint,@P1 varchar(8000),@P2 varchar(8000),@P3 varchar(8000))exec pPrcEndConnao02 @P0,@P1,@P2,@P3
resource-list
keylock hobtid=72057666620227584 dbid=10 objectname=MYDB.dbo.tVarConn indexname=PKtVarConn id=lock495af880 mode=X associatedObjectId=72057666620227584
owner-list
owner id=process48153948 mode=X
waiter-list
waiter id=process48094508 mode=X requestType=wait
keylock hobtid=72057666620227584 dbid=10 objectname=MYDB.dbo.tVarConn indexname=PKtVarConn id=lock1d7ff99b80 mode=X associatedObjectId=72057666620227584
owner-list
owner id=process48094508 mode=X
waiter-list
waiter id=process48153948 mode=X requestType=wait
我错过了什么?这两个怎么会卷入上面的僵局呢?我如何重现它以便测试可能的解决方案?
抱歉,如果这太长了或者我错过了什么...第一次发帖! :)
环境
Parent table:
Name Owner Type
--------- -------- -------------
tConn dbo user table
Column_name Type Computed Length Prec Scale Nullable TrimTrailingBlanks FixedLenNullInSource Collation
-------------- ----------- ----------- --------- ----- ----- ----------- ---------------------- ------------------------- ----------------------------
nConn int no 4 10 0 no (n/a) (n/a) NULL
Col1 smallint no 2 5 0 no (n/a) (n/a) NULL
Col2 char no 23 no no no SQL_Latin1_General_CP1_CI_AI
Col3 datetime no 8 no (n/a) (n/a) NULL
Col4 char no 20 no no no SQL_Latin1_General_CP1_CI_AI
Col5 datetime no 8 no (n/a) (n/a) NULL
Col6 varchar no 50 yes no yes SQL_Latin1_General_CP1_CI_AI
Col7 char no 1 no no no SQL_Latin1_General_CP1_CI_AI
Col8 smallint no 2 5 0 no (n/a) (n/a) NULL
Col9 smallint no 2 5 0 no (n/a) (n/a) NULL
Col10 smallint no 2 5 0 no (n/a) (n/a) NULL
Col11 decimal no 9 10 0 no (n/a) (n/a) NULL
Col12 decimal no 5 5 0 yes (n/a) (n/a) NULL
HashID tinyint yes 1 3 0 no (n/a) (n/a) NULL
Identity Seed Increment Not For Replication
----------- ------ ----------- -------------------
nConn 1 1 0
index_name index_description index_keys
------------- ------------------------------------------------------ -----------------
Idx1tConn nonclustered located on schPartConn Col2
Idx2tConn nonclustered located on schPartConn Col1, Col4, Col7
PKtConn clustered, unique, primary key located on schPartConn HashID, nConn
constraint_type constraint_name delete_action update_action status_enabled status_for_replication constraint_keys
-------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------- ------------- ------------- -------------- ---------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
FOREIGN KEY FktAplic01 No Action No Action Enabled Is_For_Replication Col1
REFERENCES MYDB.dbo.tAplic (Col1)
PRIMARY KEY (clustered) PKtConn (n/a) (n/a) (n/a) (n/a) HashID, nConn
Table is referenced by foreign key
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MYDB.dbo.tVarConn: FktConn01
这是child table:
Name Owner Type
---------- ------- -----------
tVarConn dbo user table
Column_name Type Computed Length Prec Scale Nullable TrimTrailingBlanks FixedLenNullInSource Collation
-------------- ---------- ----------- -------- ----- ----- ----------- --------------------- ---------------------- -----------------------------
nConn int no 4 10 0 no (n/a) (n/a) NULL
iVarConn char no 20 no no no SQL_Latin1_General_CP1_CI_AI
rVarConn varchar no 8000 no no no SQL_Latin1_General_CP1_CI_AI
HashID tinyint yes 1 3 0 no (n/a) (n/a) NULL
index_name index_description index_keys
--------------- -------------------------------------------------------- ------------------------
PKtVarConn clustered, unique, primary key located on schPartConn HashID, nConn, iVarConn
constraint_type constraint_name delete_action update_action status_enabled status_for_replication constraint_keys
------------------------ ------------------ ------------- ------------- -------------- ---------------------- ----------------
FOREIGN KEY FktConn01 Cascade No Action Enabled Is_For_Replication HashID, nConn
REFERENCES MYDB.dbo.tConn (HashID, nConn)
PRIMARY KEY (clustered) PKtVarConn (n/a) (n/a) (n/a) (n/a) HashID, nConn, iVarConn
No foreign keys reference table 'tVarConn', or you do not have permissions on referencing tables.
存储过程:
CREATE PROCEDURE [dbo].[pInsVarConn] (
@nConn int,
@iVarConn char(20),
@rVarConn varchar(8000)
)
AS
BEGIN
SET NOCOUNT ON
INSERT INTO tVarConn (nConn, iVarConn, rVarConn)
VALUES (@nConn, @iVarConn, @rVarConn)
END
go
CREATE PROCEDURE [dbo].[pPrcInsVarConnao01] (
@nConn int,
@iVarConn char(20),
@rVarConn varchar(8000)
)
AS
BEGIN
SET NOCOUNT ON
DECLARE @HashID tinyint
SET @HashID =CONVERT([tinyint],abs(@nConn%(72)),(0))
IF EXISTS(SELECT TOP 1 1 FROM tVarConn WITH(NOLOCK) WHERE nConn = @nConn AND HashID = @HashID AND iVarConn = @iVarConn)
BEGIN
exec [pUpdtVarConn] @nConn, @iVarConn, @rVarConn
END
ELSE
BEGIN
exec [pInsVarConn] @nConn, @iVarConn, @rVarConn
END
END
go
CREATE PROCEDURE [dbo].[pPrcEndConnao02](
@IdConnao int,
@SeqGen char(23),
@CurrEnd char(50),
@Valid char(1) = 'N'
)
AS
DECLARE @HashID tinyint
DECLARE @EndUs char(50)
DECLARE @StConnao char(1)
DECLARE @RC smallint
BEGIN
SET NOCOUNT ON
SET @HashID =CONVERT([tinyint],abs(@IdConnao%(72)),(0))
SELECT
@EndUs = Col6,
@StConnao = Col7
FROM
dbo.tConn WITH(NOLOCK)
WHERE
nConn = @IdConnao AND
HashID = @HashID AND
Col2 = @SeqGen
IF(@@ROWCOUNT = 0)
BEGIN
SET @RC = -5014
END
ELSE
BEGIN
IF(@stConnao = 'F')
BEGIN
SET @RC = -5012
END
ELSE
BEGIN
UPDATE dbo.tConn
SET Col7 = 'F'
WHERE nConn = @IdConnao
AND HashID = @HashID
AND Col2 = @SeqGen
DELETE FROM dbo.tVarConn WHERE nConn = @IdConnao AND HashID = @HashID
SET @RC = 0
END
END
SELECT @RC AS Ret
END
非常感谢!
英尺
发现 java 应用程序打开的外部事务中有资源被锁定,该应用程序禁用了 运行 几个存储过程的自动提交设置,然后提交。
这解释了 trancount=2。
英尺