我有两个假想问题:
UPDATE BankAccounts SET HomePhone = '+1 252-555-0912'
WHERE AccountNumber = 14400000619
并且
SELECT * FROM BankAccounts
WHERE HomePhone = '555-1212'
在一个没有额外索引的假设表格上:
CREATE TABLE BankAccounts
(
AccountNumber bigint NOT NULL PRIMARY KEY CLUSTERED,
FirstName nvarchar(50) NOT NULL,
MiddleName nvarchar(50) NULL,
LastName nvarchar(50) NOT NULL,
HomePhone varchar(50) NULL,
IsClosed tinyint DEFAULT 0
)
一切都会变得很好。如果我在HomePhone
上添加索引:
CREATE INDEX IX_BankAccounts_HomePhone ON BankAccounts
( HomePhone)
现在我的
SELECT
语句可能成为死锁的受害者:
一般的建议是:事务(进程ID 169)与另一个进程在锁资源上发生死锁,并被选择为死锁受害者。重新运行该事务。
- 以相同的顺序访问表
- 尽可能缩短事务时间
- 我正在以相同的顺序访问(一个)表(1选1等于1)
- 事务是一个单一的语句;我无法再缩短了
我正在考虑将我的事务隔离级别更改为
READ UNCOMMITTED
(即取消完整性),但由于我实际上正在处理一个金融系统,我不愿意允许客户两次提取他的全部余额。我能找到的唯一其他解决方案来自KB Article 83252:
我想这是在说:"无法胜利,不要尝试" 还有其他的解决方案吗?SQL Server技术公告 - 如何解决死锁
……无法避免死锁。这就是为什么前端应用程序应该设计来处理死锁。
在一个设计良好的应用程序中,前端应用程序应该捕获1205错误,重新连接到SQL Server,然后重新提交事务。