ロック レベルと分離レベル
さまざまなデータベース システムによって、多様なロック レベルおよび分離レベルをサポートします。以下のトピックでは、ロック レベルおよび分離レベルについて、またこれらの設定が、取得するデータにどのように影響するかについて説明します。
ロック
ロックとは、ユーザーがデータベースのテーブルやレコードにアクセスするのを制限する処理です。複数のユーザーが同じテーブルやレコードに同時にアクセスする可能性がある場合に、ロックをかけます。テーブルやレコードをロックすると、一度に 1 人のユーザーだけがデータに影響する処理を行えるようになります。
ロック制御は、複数のユーザーが、データベースの同じレコードに同時にアクセスしたり変更する場合に特に重要です。複数のユーザーが同時に使えるデータベースは便利ですが、問題が発生することもあります。たとえば、ロックしていない場合、2 人のユーザーが同時に同じレコードを変更しようとすると、正確なデータが取得できなかったり、一方のユーザーが必要とするデータをもう一方のユーザーが削除してしまう可能性があります。しかし、いったん 1 人のユーザーがアクセスしたレコードを、他のユーザーが一時的に変更できないようにロックできるようにしておくと、このような問題は発生しません。ロックすることによって、データベースへの同時アクセスによる問題の発生を最小限に抑えることができます。
分離レベル
分離レベルとは、データの一貫性を高めるためにデータベース システムで採用される特別なロック方法です。分離レベルが高いほど、そのロック方法も複雑になります。データベースで使用される分離レベルによって、データの一貫性に関連する次の事象がトランザクションで発生するかどうかが決まります。
Dirty reads (ダーティー リード) | ユーザー 1 が行を変更します。ユーザー 1 がコミットする前に、ユーザー 2 が同じ行を読み取ります。ユーザー 1 がロールバックします。ユーザー 2 は、実際にはデータベースに存在しない行を読み取ったことになります。これによって、ユーザー 2 は誤ったデータに対して判断を下すことになるかもしれません。 |
Non-repeatable reads (反復不可能な読み取り) | ユーザー 1 が行を読み取りましたがコミットしません。ユーザー 2 がその同じ行を修正または削除し、それをコミットします。ユーザー 1 がもう一度同じ行を読み取ったときは、その行が変更または削除されています。 |
Phantom reads (ファントム リード) | ユーザー 1 は、検索条件を使用して複数行のセットを読み取りましたがコミットはしません。ユーザー2 がこの検索条件を満たす行を挿入し、コミットします。ユーザー 1 が検索条件を使ってもう一度読み取ったときには、前になかった行が存在することになります。 |
分離レベルとは、データベース システムで、上記の事象が発生するのを防げるかどうかを示すレベルです。ANSI(American National Standards Institute:米国規格協会)によって、次の 4 つの分離レベルが定められています
•Read uncommitted (0) (コミットされていない読み取り)
•Read committed (1) (コミットされた読み取り)
•Repeatable read (2) (反復可能な読み取り)
•Serializable (3) (直列化可能)
0 から 3 へとレベルが高くなるほど、トランザクションのデータの一貫性も高くなります。一番低いレベルでは、上の 3 つの事象がすべて発生する可能性があります。一番高いレベルでは、どの事象も発生しません。このような事象が発生するのを防げるかどうかは、各レベルで使う、次のようなロック方法によって決まります。
Read uncommitted (0) (コミットされていない読み取り) | データベースを変更するときにロックがかかり、トランザクションの終わり(EOT)まで維持されます。データベースの読み取りには、ロックがかかりません。 |
Read committed (1) (コミットされた読み取り) | データベースの読み取りと変更時にロックがかかります。読み取り後にロックは解除されますが、変更されたオブジェクトのロックは EOT まで維持されます。 |
Repeatable read (2) (反復可能な読み取り) | データベースの読み取りと変更時にロックがかかります。変更されたすべてのオブジェクトのロックは EOT まで維持されます。データの読み取りロックは、EOT まで維持されます。変更不可能なアクセス構造(インデックスおよびハッシュ構造など)のロックは読み取り後に解除されます。 |
Serializable (3) (直列化可能) | DataSet の影響を受ける行に、EOT までロックがかかります。変更されたアクセス構造、およびクエリで使われた構造がすべて EOT までロックされます。 |
表
67 では各分離レベルにおいて発生するデータ一貫性の事象を示します。
表 67 分離レベルとデータの一貫性
レベル | Dirty Read(ダーティー リード) | Nonrepeatable Read(反復不可能な読み取り) | Phantom Read(ファントム リード) |
---|
0, Read uncommitted (コミットされていない読み取り) | Yes | Yes | Yes |
1, Read committed (コミットされた読み取り) | No | Yes | Yes |
2, Repeatable read (反復可能な読み取り) | No | No | Yes |
3, Serializable (直列化可能) | No | No | No |
分離レベルが高いほどデータの一貫性は高くなりますが、逆に、個々のユーザーの同時処理性は低くなります。同時処理とは、複数のユーザーが同時にデータにアクセスして変更することです。分離レベルが上がるに従って、使用されるロック制御が原因で、同時処理上の問題が発生する確率が高くなります。
検討事項:分離レベルが高くなるほどロック制御が厳しくなり、ユーザーが、別のユーザーによってかけられたロックが解除されるのを待つ時間が長くなります。分離レベルと同時処理性には、このような逆比例的な関係があるので、分離レベルを選択する前にユーザーがデータベースをどのように使用するか検討しておく必要があります。データの一貫性と同時処理性のどちらがより重要かを考慮して、使用する分離レベルを決めてください。
ロック モードとレベル
データベース システムによって使用するロック モードは異なりますが、通常、「共有ロック」と「排他ロック」という 2 種類の基本モードがあります。共有ロックでは、複数のユーザーが単一オブジェクトを参照することが可能です。1 人のユーザーがレコードに共有ロックをかけると、2 番目に同じレコードにアクセスしたユーザーも共有ロックをかけることができます。ただし、2 番目のユーザーは、そのレコードに排他ロックをかけることはできません。排他ロックとは、そのロックを取得したユーザーへの独占的な権利です。1 人のユーザーがレコードに排他ロックをかけると、2 番目のユーザーは、同じレコードにどの種類のロックもかけられなくなります。
データベース システムで使用するロック レベルは、パフォーマンスと同時処理性にも影響します。ロック レベルによって、データベース内でロックされるオブジェクトのサイズが決まります。たとえば、データベース システムの多くで、テーブル全体、および個々のレコードをロックすることができます。また、ページ レベルのロック(ロック レベルは中程度)もよく使われます。1 ページには 1 つまたは複数のレコードが入っていますが、これは通常、1 回のディスク アクセスでディスクから読み取られるデータの量です。ページ レベルのロックの大きな欠点は、1 人のユーザーがレコードをロックすると、同じページに保存されているほかのレコードを 2 番目のユーザーがロックできないことです。