在这里发布问题和一个答案。也许有人有更好的答案...
如果开发人员不小心打开了与数据库的第二个连接而不是重用现有的连接(可能已经有一个打开的事务),那么即使是单个用户也可以编写触发死锁的代码。某些 O/RM 和 LINQ 框架使这个错误变得容易。
以下是纯 SQL 术语中的场景:
--Setup:
CREATE TABLE Vendors(VendorID int NOT NULL, VendorName nvarchar(100) NOT NULL, ExtraColumn int not null, CONSTRAINT PK_Vendors PRIMARY KEY CLUSTERED(VendorID))
GO
INSERT INTO Vendors(VendorID,VendorName,ExtraColumn) VALUES (1, 'Microsoft', 12345)
INSERT INTO Vendors(VendorID,VendorName,ExtraColumn) VALUES (2, 'Oracle', 12345)
--Connection 1:
BEGIN TRANSACTION
UPDATE Vendors SET ExtraColumn = 222 WHERE VendorID = 2
--Connection 2:
BEGIN TRANSACTION
SELECT VendorName FROM Vendors WHERE VendorID = 1
当数据很小时,此代码(以及生成它的 c#/java/ORM/LINQ/任何生成它的代码)可能会在开发/测试中愉快地运行,但是当数据/内存配置文件在生产中更改并且锁从行升级到页到表。
那么如何在我的测试环境中强制将锁升级到表级别,以便我可以清除任何这样的错误(代码打开第二个连接)?
锁升级完全由 SQL Server 数据库引擎控制,无法预测何时会从行锁升级到表锁。我不会重复您可以在此处找到的所有详细信息,但需要特别注意的是:“当...数据库引擎实例中的锁数量超过内存或配置阈值时,将触发锁升级。” 这意味着它可能与我精心设计的代码和完美选择的索引完全无关。