インテントロックとは?

 

神谷 雅紀
Escalation Engineer

あるフォーラムでインテントロックが取り立たされているのを見かけたので、今回はインテントロックを話題にしたいと思います。

 

ロックに関わる用語

ロックリソース ロックの対象となるリソース。 例えば、「テーブル A にロックを獲得する」と言った場合のロックリソースは「テーブル A」です。
ロックモード 「共有 (Shared, S)」「排他 (Exclusive, X)」「更新 (Update, U)」など、排他制御の度合い。
ロックの互換性 同じロックリソースに同時に獲得することのできるかどうか。 同時に獲得できるロックモードのロックは「互換性がある」と表現します。反対に、同じロックリソースに同時に獲得することのできないロックモードのロックは「互換性がない」と表現します。
ロックの粒度 ロックリソースの階層関係または大小関係を表す。 例えば、行 (RID) に獲得したロックはページ (PAGE) に獲得したロックよりも小さい粒度であり、ページに獲得したロックはテーブル (TABLE) に獲得したロックよりも小さい粒度です。

 

インテントロックとは?

インテントロック (Intent Lock) とは、ロックモードのひとつで、より粒度の低いロックリソースにロックを保持していることを示すためのロックです。

以下の種類があります。

インテント共有 (intent shared) IS より粒度の低いロックリソースに共有ロック (S) を保持していることを示します。
インテント排他 (intent exclusive) IX より粒度の低いロックリソースに排他ロック (X) を保持していることを示します。
インテント更新 (intent update) IU より粒度の低いロックリソースに更新ロック (U) を保持していることを示します。

 

なぜインテントロックは必要なのか?

ロックは、SQL Server 内部コンポーネントのひとつであるロックマネージャ (Lock Manager) によって一元管理されています。ロックマネージャは、獲得済みロックの情報を保持し、また、ひとつのロックリソースに対して獲得されるロックを制御します。

例えば、ロックリソース「テーブル A 」にロックモード S のロックが既に獲得されている状態で、同じ「テーブル A」にロックモード X を獲得しようとすると、互換性がないため、ロックマネージャはロックモード X の獲得は許可しません。一方、ロックリソース「テーブル A 」にロックモード S のロックが獲得されている状態で、テーブル A に属する「行 B」に ロックモード X を獲得しようとしても、ロックマネージャはそれを許可します (これは、インテントロックというものが存在しない場合の仮の話です。実際にはインテントロックがあるため許可されません。)。その理由は、ロックリソースが「テーブル A」「行 B」と異なるロックリソースからです。ロックマネージャは、行 B がテーブル A に属していることを知りません。ロックマネージャは、単にひとつのロックリソースに対して獲得されるロックを制御するだけで、ロックの粒度は管理してません。

これでは、テーブル A をロックして読み取っているにも関わらず、テーブル A に属する行 B が更新されてしまう恐れがあります。

では、テーブル A に S ロックが獲得されている時に、テーブル A に属する行 B に X ロックを獲得させないようにするためにはどうすればいいでしょうか?

それを実現するためには、行 B がテーブル A に属していることを知っているロックの要求元が、行 B に X ロックを要求する前に、テーブル A にロックを獲得して、テーブル A に対して他のロックが獲得されないようにすることが必要です。

これを実現するために必要になるのが、インテントロックというロックモードです。

インテントロック同士はすべて互換性があるため、あるトランザクションが行 B に X ロック、テーブル A に IX ロックを獲得している状態であっても、別のトランザクションは行 C に S ロック、テーブル A に IS ロックを獲得することができます。さらに、IX は S, U, X とは互換性がないため、行 B に X を保持している間にテーブルに S, U, X を獲得されるということもなくなります。

 

結論

インテントロックは、SQL Server を使用する上では、基本的に、ほとんど意識する必要のないロックです。