我们在 AWS 上使用 Microsoft SQL Server 2017 标准版(64 位),并且遇到无法解释的死锁事件。
我们正在尝试从不同的进程更新不同的唯一行,表和页面升级被禁用,sqlserver 使用键锁,我们仍然遇到死锁。
profiler 中的数据显示每个进程在不同的行上工作,所以我们不明白为什么会发生这种死锁。
** 我们认为我们设法在测试表中重现了这个死锁,但我们仍然没有对此死锁的解释(表和页面升级被禁用)。
CREATE TABLE TestTable
(
ID CHAR(8) NOT NULL PRIMARY KEY,
Val CHAR(1)
)
--in session 1
BEGIN TRANSACTION
DECLARE @INX bigint ;
DECLARE @INX2 nchar(8);
SET @INX = NEXT VALUE FOR SequenceExample ;
set @INX2 = @INX;
Print (@INX2)
WAITFOR DELAY '00:00:05'
INSERT INTO [dbo].[TestTable]
([ID]
,[Val])
VALUES
(@INX2,'Y');
WAITFOR DELAY '00:00:05'
UPDATE [dbo].[TestTable]
SET Val='X'
WHERE ID= @INX2
WAITFOR DELAY '00:00:05'
COMMIT ;
--in session 2
BEGIN TRANSACTION
DECLARE @INX bigint ;
DECLARE @INX2 nchar(8);
SET @INX = NEXT VALUE FOR SequenceExample ;
set @INX2 = @INX;
Print (@INX2)
WAITFOR DELAY '00:00:05'
INSERT INTO [dbo].[TestTable]
([ID]
,[Val])
VALUES
(@INX2,'Y');
WAITFOR DELAY '00:00:05'
UPDATE [dbo].[TestTable]
SET Val='X'
WHERE ID= @INX2
WAITFOR DELAY '00:00:05'
COMMIT ;
所以死锁问题是由列数据类型 char(8) 和变量数据类型 nchar(8) 之间的不匹配引起的。当两个事务同时开始时,不匹配迫使该数据库转换导致死锁的数据,尽管每个事务都在另一条记录上工作。
在我们将列数据类型更新为 nchar 后问题得到解决。(与变量相同)