UPDATE
documentationによれば、UPDATE
は常にテーブル全体の排他ロックを獲得します。しかし、更新される行が決定される前、または実際の更新の直前に排他ロックが取得されるかどうかは疑問です。単一のテーブルのみを更新するトランザクションは常に分離されていますか?
私の具体的な問題は、私はこのように私のUPDATE
でネストされたSELECT
していることである。
UPDATE Tasks
SET Status = 'Active'
WHERE Id = (SELECT TOP 1 Id
FROM Tasks
WHERE Type = 1
AND (SELECT COUNT(*)
FROM Tasks
WHERE Status = 'Active') = 0
ORDER BY Id)
は今、私は本当に並列であれば、その後Status = 'Active'
と正確に一つの タスクがあることが保証されているかどうかを疑問に思って
UPDATE Tasks
SET Status = 'Active'
WHERE Id = (SELECT TOP 1 Id
FROM Tasks
WHERE Type = 2 -- <== The only difference
AND (SELECT COUNT(*)
FROM Tasks
WHERE Status = 'Active') = 0
ORDER BY Id)
両方のステートメントでロックを取得する前に変更する行が決定された場合は、私が避けなければならない2つの活動があります。
この場合、どのように防止できますか?トランザクションレベルをSERIALIZABLE
に設定したり、ロックヒントをつぶしたりせずにそれを防ぐことはできますか?
Is a single SQL Server statement atomic and consistent?の回答から、入れ子になったSELECT
が別のテーブルにアクセスするときに問題が発生することがわかりました。しかし、更新されたテーブルだけが関係している場合、この問題を気にする必要があるかどうかはわかりません。
ドキュメントはとにかく間違っていること。通常、更新はテーブル全体をロックしません。 –
ええ、ありがとう、ありがとう。しかし、正しい文書はどこにありますか? – lex82
文書は、実際には 'UPDATE'がテーブル全体をロックしているとは言いません。それは、排他ロックを取得すると言いますが、排他ロックはテーブル全体にある必要はありません。 –