.NETエンタープライズWebアプリケーション 開発技術大全
― エンタープライズWebアプリ開発に必要な知識と設計セオリー ―


SQL Serverのロック管理

マイクロソフト コンサルティング本部 赤間 信幸
2005/03/01

Page1 Page2 Page3 Page4

.NETエンタープライズWebアプリケーション
開発技術大全 Vol.5
トランザクション設計編
 2005年3月22日発売!

 本記事は、日経BPソフトプレスマイクロソフトプレスより2005年3月22日に発行予定の書籍『.NETエンタープライズWebアプリケーション開発技術大全 Vol.5 トランザクション設計編』より、同社の許可を得てその内容を転載したものです。

 同書はマイクロソフトのコンサルタントが執筆した.NETシステム設計/構築のための技術解説書で、全5巻で構成されています。

 シリーズ最終巻となるこの第5巻では、大規模システムにおけるデータベース処理には欠かすことのできないトランザクション処理について、詳細かつ実践的に、多くの図版を交えながら解説しています。

 具体的には、第1部(1〜3章)でトランザクションの基礎とSQL Serverにおける同時実行制御の仕組み、第2部(4〜7章)では、分散トランザクションに不可欠な「自動トランザクション」について、そして第3部(8〜9章)では、より複雑なトランザクション処理として、いくつかの処理パターンにおける適切な設計方法についての解説となっています。

 本記事の内容は、第1部の「第2章 SQL Serverのロック管理」からの転載です。最適なトランザクション処理を正しく行うために.NETのシステムではどのような設計・実装が必要となるかを理解するには、データベースであるSQL Serverの同時実行制御(ロック・メカニズム)の仕組みについて、まず熟知しておく必要があります。

 なお、書籍の詳細については本記事の最後に表記しています。

ご注意:本記事は、前挙の書籍の内容を改訂することなく、そのまま転載したものです。このため用字用語の統一ルールなどは@ITのそれとは一致しません。あらかじめご了承ください。

 現在の主要商用データベースにおける、トランザクション制御のための同時実行制御方式は大きく分けて2つある。

 

・ ロック方式
  ・ 対象リソースに対してロックを取得し、同時実行に関する問題がないことを確認してから、実際のデータを読み書きしていく方式。
  ・ マイクロソフトのSQL Serverや、IBMのDB2などで採用されている。
 
・ マルチバージョニング方式(時間ドメインアドレッシング方式)
  ・ データベースに対して行われた更新内容をロールバックセグメントなどで世代管理しておくことにより、あるトランザクション内での読み取り一貫性を保証する方式。
  ・ オラクル社のOracleで採用されている※1
 
*1 なおSQL Server 2005(コードネームYukon)では、Oracleのマルチバージョニングに似た新たな分離レベルとしてSNAPSHOT分離レベルと呼ばれるものが導入される予定である。詳細は以下の資料を参照のこと。SQL Server 2005 Beta 2 Snapshot Isolation(http://www.microsoft.com/technet/prodtechnol/sql/2005/SQL05B.mspx

 ロック方式とマルチバージョニング方式にはそれぞれトレードオフがあり、アーキテクチャの優劣を一般論として一意に決めることはできない。また、どちらの方式を利用している場合であっても、データベースは「処理結果のACID保証」しか行ってくれない。このためすべてのトランザクション処理をデータベースにコミットさせるためには、アプリケーションに何らかの工夫が必要になる。結論を先に述べると、以下の2つのルールを守るように設計や実装を工夫する必要がある。

  • すべてのトランザクションが、各リソースに対して同じ順番でアクセスを行うこと。

  • 1つのトランザクションの中で2種類のロックを要求する場合、最初に最も制限の強いモードのロックを獲得すること。

 確かに結論自体は単純なのだが、このルールを正しく理解するためにはデータベースの同時実行制御の内部挙動について深く理解しておく必要がある。本章ではSQL Serverの場合を採り上げて、その内部挙動を詳細に解説する。

2.1 SQL Serverのロックメカニズムの基礎

 SQL Serverのロックメカニズムに関しては、SQL Serverのオンラインヘルプや『アーキテクチャ徹底解説Microsoft SQL Server 2000』※2などで詳細に解説されているが、これらを読んでいきなり全貌を理解するのは難しい。そこで本書では、SQL Serverの基礎となっている3種類のロックについてまず説き起こし、これを起点に解説を進めていくこととする。

*2 http://www.microsoft.com/japan/info/press/JPN_ViewMsPress.asp?Book_id=788&list_id=1

2.1.1 主なロックとその互換性

 SQL Serverはリソース上での処理衝突を制御するため、まず対象リソースに各種のフラグを立て、他のユーザに対して自分が処理中であることを示した上で、実際のSQL処理を行うようになっている。このフラグのことをロックと呼ぶ(図2-1)。

図2-1 SQL Server内部でのフラグによる同時実行制御のイメージ

A. 主な3種類のロックとそれぞれの意味

 SQL Server内部で利用されるフラグは全部で9種類あるが、その中でも特に重要なものは以下の3つである。この3種類のロックは以降の解説の基礎となるため、意味も併せて完全に記憶して頂きたい(図2-2)。

図2-2 SQL Server内部で利用される主なロック
 
・ 共有ロック(Share Lock, S-Lock)
  ・ 自分がそのデータを読み出していることを、他のユーザに示すために立てるフラグ。
 
・ 更新ロック(Update Lock, U-Lock)
  ・ 自分がそのデータを後で更新する予定であることを、他のユーザに示すために立てるフラグ。
 
・ 排他ロック(eXclusive Lock, X-Lock)
  ・ 自分がそのデータを更新していることを、他のユーザに示すために立てるフラグ。

 共有ロックと排他ロックは、それぞれ読み取り処理と書き込み処理の直前に対象リソースに対して立てるフラグである。これに対して更新ロックは、「まずはそのデータを読み出すが、後でそのデータを更新する予定である」ことを宣言する、いわば「更新予約フラグ」である。この更新予約フラグの適切な使い方に関しては、2.4.3項の「B. 変換デッドロックの防止方法」で解説する。

B. ロックの互換性(Lock Compatibility)

 状況次第では、1つのリソース上に複数のフラグを同時に立てることも可能である。図2-3にこの様子を示す。フラグの立て方にはルールがあるが、このルールは少し意味を考えてみると容易に納得できるだろう。

図2-3 すでに立てられているフラグと、これから立てようとするフラグの間の関係

 いくつか例を挙げてみよう。

  • 同一データに対して複数人が同時に共有ロックをかけることができる。これは、読み出しを行うだけなら、何人が同時に行ってもデータ不整合が生じる恐れがないためである。

  • 排他ロックがかけられているデータを、他のユーザが読み出すことは許されない。これは、読み取ったデータがまだコミットされておらず、元に巻き戻される可能性が残っているためである。すなわち、排他ロックがかかっているリソースに対して、さらに共有ロックをかけてデータを読み出すことはできない。

  • すでに排他ロックがかけられているデータに対して、さらに排他ロックをかけてデータを更新することは当然できない。

 この例からも分かるように、あるデータ(対象リソース)に対してすでにロックがかけられている場合、他のユーザ(トランザクション)が追加で立てることができるロックは自ずと限られてくる。このルールを整理したものが表2-1である。SQL Serverはこの表に定められたルールに従って動作することにより、データ不整合問題の発生を防いでいる。この表のことを、ロックの互換性(Lock Compatibility)※3と呼ぶ。 

自分が新たに取得しようとしているロック 他のユーザによりすでにかけられているロック
共有 (S) 更新 (U) 排他 (X)
共有 (S) 不可
更新 (U) 不可 不可
排他 (X) 不可 不可 不可
表2-1 ロックの互換性(Lock Compatibility)

*3 「互換性」という言葉を、アプリケーションの「互換性」のような意味合いで捉えると誤解を招く。ロックの互換性とは、ロックがすでにかけられたリソースに、さらにロックを追加できるか否かを定めた「ルール表」であると覚えると間違いがないだろう。

 このロックの互換性の表は暗記する必要があるが、闇雲に暗記せずとも、多少意味を考えればほぼ自明の理として導ける。このロック互換表の意味を日本語で表現すると、以下のようになる。表2-1と実際に比較してみて頂きたい。

・ S + S = 可:読み出しだけなら何人でも同時にできる
  ・ ユーザαがS-Lockを取得している最中に、ユーザβがS-Lockを取得してデータを読み出すことができる。
 
・ X + X = 不可:同時に書き込みができるのは一人に限られる
  ・ ユーザαがX-Lockを解放する前に、ユーザβがX-Lockを取得してデータを更新することはできない。つまり、他人が書き込んでいる最中のデータを更新することはできない。
 
・ U + X = 不可:更新予約のかかっているデータを、別のユーザが更新することはできない
  ・ ユーザαが更新予約をしている場合、ユーザβがX-Lockを取得してデータを更新することはできない。
 
・ U + U = 不可:2人が同時に更新予約をかけることはできない
  ・ ユーザαが更新予約をしている場合、ユーザβが重ねてU-Lockを取得して更新予約することはできない。
 
・ U + S = 可:更新予約がかかっていても、読み出しだけならできる※4
  ・ ユーザαがU-Lockを取得している場合でも、ユーザβがS-Lockを取得してデータを読み取ることはできる。

*4 ここで解説した内容のうちで、違和感を覚えやすいのはこの「U + S」に関する項目であると思われるが、このような挙動を行っても全く問題なくACID特性を満たすことができる。これは、ユーザβの処理がユーザαの前に直列処理された場合と等価な処理結果となるためである。

 次に、この3種類のロックがSQL Server上のどのようなリソースに対してかけられるのかについて解説する。

 

 INDEX
  .NETエンタープライズWebアプリケーション 開発技術大全
  SQL Serverのロック管理
  1.SQL Serverのロックメカニズムの基礎
    2.SQL Serverの内部構造とロック対象となるリソース
    3.分離レベルによるロック保持期間の変化
    4.分離レベルによるインデックスキーに対するロックの種類の変化
 
インデックス・ページヘ  「.NETエンタープライズWebアプリケーション開発技術大全」

@IT Special

- PR -

TechTargetジャパン

Insider.NET フォーラム 新着記事
  • Flow(JavaScript用静的型チェッカー) (2017/1/17)
     FlowはJavaScript用の静的型チェッカー。型推測機構や型注釈を利用することで、型安全なプログラミングを支援する
  • Pythonの例外をサクサク理解しよう (2017/1/13)
     Pythonで例外を取り扱うための機構であるtry文やraise文などについて、サンプル多めで見ていこう
  • 構文:キャッチした例外をリスローするには? (2017/1/11)
     例外の処理時には何らかの理由で、キャッチした例外をリスローしなければならないときがある。C#やVBでこれを適切に行う方法を解説する
  • ジャグ配列 (2017/1/10)
     ジャグ配列とは「配列の配列」を表す用語。ジャグ配列では配列の特定の次元の各要素が参照する配列の要素数が異なる場合がある
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

イベントカレンダー

PickUpイベント

- PR -

アクセスランキング

もっと見る

ホワイトペーパーTechTargetジャパン

注目のテーマ

Insider.NET 記事ランキング

本日 月間
ソリューションFLASH