私は2つの架空のクエリを持っています:
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
声明はデッドロックの犠牲者になる可能性があります:
Tranasction(プロセスID 169)は、別のプロセスでロックリソースでデッドロックされ、デッドロックの犠牲者として選択されました。トランザクションを再実行します。
一般的な提案は次のとおりです。
- 同じ順序でテーブルにアクセスする
- トランザクションをできるだけ短くする
この場合を除いて:
- 私は同じ順序で(1つの)テーブルにアクセスしています(1を選択1は1です)
- トランザクションは単一のステートメントです。それより短くすることはできません
このようなデッドロックを解消するための長期的な解決策は何ですか?
トランザクション分離レベルをに変更する(つまり、整合性を排除する)ことを検討してREAD UNCOMMITTED
いましたが、実際には金融システムを扱っているため、顧客が残高全体を2回引き出すことを躊躇しています。
私が見つけることができる他の唯一の解決策はKBArticle83252から来ています:
SQLServerテクニカルブリテン-デッドロックを解決する方法
...デッドロックは避けられません。そのため、フロントエンドアプリケーションはデッドロックを処理するように設計する必要があります。
適切に設計されたアプリケーションでは、フロントエンドアプリケーションは1205エラーをトラップし、SQL Serverに再接続してから、トランザクションを再送信する必要があります。
私が推測しているのは、 「勝てない、やってはいけない」ということです。
他に何か?