たまたま試す機会があったのでメモ。
テーブル ヒント (Transact-SQL) - SQL Server | Microsoft Docs
には HOLDLOCK は SERIALIZABLE 相当と書かれていて、
SERIALIZABLE では、
SERIALIZABLE 分離レベルで実行しているトランザクションと同じセマンティクスで、スキャンが実行されます。
となっているので、ドキュメント通りなんだけど試したから書いとく。
例1:
存在しない行に UPDLOCK を掛けても、ロックは取られない。
なので、他のトランザクションで行を追加されてしまう。
ロック掛けるセッション
begin tran select * from [Table] (UPDLOCK) where Id = 6
追加するセッション
begin tran insert into [Table] values (6, 'abcabc') select * from [Table] rollback
Id = 6 が追加される。
例2:
HOLDLOCK にすると、行を追加されない。
ロック掛けるセッション
begin tran select * from [Table] (HOLDLOCK) where Id = 6
追加するセッション
begin tran insert into [Table] values (6, 'abcabc') select * from [Table] rollback
ロックが解放されるまで追加できない。
ロック状況
範囲でロックを取っているので、今回の場合は Id = 6 だけではなく、6 以上の値では insert 出来ない。
逆に Id = 0 や -1 は insert 可能。
Id が 1 と 5 のデータしかない場合に、Id = 3 で HOLDLOCK 掛けたら、1 より小さい値や、5 より大きい値はロックの範囲外。
2, 3, 4 はロックの範囲内。
多分こんな認識で大丈夫のはず。