Nic*_*aro 3 sql-server-2008 sql-server deadlock sql-server-2008-r2 locking
使用 SQL Server 2008 R2:
我目前正在尝试追踪我们遇到的死锁问题的原因。不知道该往哪里转。这是设置。
TABLE Scores:
id INT IDENTITY(1,1),
first_name VARCHAR(50),
last_name VARCHAR(50),
player_id VARCHAR(50),
score INT
PRIMARY KEY/CLUSTERED INDEX:
id
NON-CLUSTERED INDEX:
first_name, last_name INCLUDES id, player_id, score
Run Code Online (Sandbox Code Playgroud)
多线程应用程序处理消息,然后为每条消息调用两个存储过程之一。
如果应用程序尚未处理用户,它将调用一个存储过程,将一行插入到表中。
如果应用程序已经处理了用户,它会更新first_name
、last_name
、scores
、 中的任何一个或全部,first_name
并且last_name
player_id
不会改变。
每个 表中只有一行player_id
。
应用程序处理消息的线程是根据 player_id 选择的,因此两个线程不会同时处理同一个玩家的消息。
INSERT 和 UPDATE 语句正在使用该WITH (ROWLOCK)
指令。
这是问题:
该进程导致死锁,线程 1 锁定主聚集索引,线程 2 锁定非聚集索引。
我不明白为什么会发生锁 - UPDATE 和 INSERT 语句正在使用行锁,并且已经过测试并证明线程没有访问相同的行。
我能做些什么来解决这个问题?
注意事项:
必须存在两个存储过程,一个是更新,一个是插入。尽管我很想切换到单个 MERGE,但这不会发生。:/
更新任何 NC 索引键都是可能导致死锁的更新。由于访问路径不同,这是典型的读写死锁。即使您更新不同的键,也不能消除冲突,因为锁是在键哈希上的,请参阅%%lockres%% 碰撞概率魔法标记:16,777,215。但是,您将问题描述为“立即”出现,这强烈表明还有其他一些因素在起作用,我们只能在缺乏实际信息的情况下进行推测。
当然,捕获死锁图并将其张贴在这里会更有用。仅仅讨论僵局的描述价值有限,因为您的描述可能是也可能不是事实,您的理解可能正确也可能不正确,我们的解释可能准确也可能不准确。