i have two hypothetical queries:
UPDATE BankAccounts SET HomePhone = '+1 252-555-0912'
WHERE AccountNumber = 14400000619
and
SELECT * FROM BankAccounts
WHERE HomePhone = '555-1212'
on a hypothetical table with no extra indexes:
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
)
and everything will be great. If i add an index on HomePhone
:
CREATE INDEX IX_BankAccounts_HomePhone ON BankAccounts
( HomePhone)
Now my SELECT
statement can be a deadlock victim:
Tranasction (Process ID 169) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
The common suggestions are to:
- access tables in the same order
- keep transactions as short as possible
Except in this case:
- i am access the (one) table in the same order (1 choose 1 is 1)
- the transactions are a single statement; i cannot get any shorter than that
What's the long-term solution to eliminate deadlocks like this?
i was considering changing my transaction isolation level to READ UNCOMMITTED
(i.e. eliminating integrity), but because i'm actually dealing with a financial system i'm hesitant to allow a customer to withdraw his entire balance twice.
The only other solution i can find comes from KB Article 83252:
SQL Server technical bulletin - How to resolve a deadlock
...deadlocks cannot be avoided. That is why the front-end application should be designed to handle deadlocks.
In a well designed application, the front-end application should trap for the 1205 error, reconnect to SQL Server, and then re-submit the transaction.
Which i guess is saying: "can't win; don't try"
Anything else?