検索

データを保護するロックの仕組み



ロックの基本

データベース上の同一データに対して書込み要求が同時に発生した場合、トランザクションが逐次化されていないと結果に矛盾が生じてしまいます(図1左)。これは、ロックの機構がない場合に一般的に発生する問題であり、ロックを適切に実装することでこの問題は解決します(図1右)。Teradataデータベースの Lock Manager は、複数のトランザクションが同一オブジェクトに対して共有できない操作を実行する場合、次のように制御します。

  1. 最初にアクセスを要求したトランザクションに対してロックを許可する。

  2. 後続のトランザクションを待ち行列に入れる。

  3. 最初のトランザクションが完了したらロックを解除し、待ち行列の中で最も古いトランザクションにロックを許可する。

なお、待ち行列でロックの取得を待機しているトランザクションがタイムアウトすることはありません。

ロックの対象範囲と種類

Teradataデータベースのロックには、ロックの対象範囲を決める“レベル”と、ロックの制約強度の種類を決める“タイプ”の 2つの概念があります。ロックのレベルには次の 3つの種類があり、SQL 文の種類に応じて自動的に決まります(表1)。

データベース・レベル・・・ データベース内の全てのテーブルの行がロックされる(CREATE、DROP、または MODIFY DATABASE文など)。

テーブル・レベル・・・ テーブル内の全ての行、インデックス、およびフォールバックの副表がロックされる(CREATE TABLE や ALTERTABLE文など)。

行ハッシュ・レベル・・・ 1つの行および同じテーブル内で同一ハッシュコードを持つ全ての行の基本コピーがロックされる(PI や USI などを使用してアクセスする DML文 ※1 など)。行ハッシュ・ロックは最も制約の少ないロックであり、他のトランザクションはテーブル内の他の行にアクセス可能である。

一方、ロックのタイプは状況に応じて以下の4 種類の強度から選択されます。これらのロック・タイプは、互いに共有できるものと競合するものがあるため、既に何らかのタイプのロックが設定されているオブジェクトに対して競合するタイプのロックを設定しようとすると、そのトランザクションは待機状態に入ります(表2)。

排他ロック・・・ ロックを設定したユーザーだけがそのオブジェクトにアクセスすることができる、最も制約の強いロックである。排他ロックを使用すると、同一オブジェクトは完全に占有になり、他のいかなるロックも設定できない。

書込みロック・・・ ロックを設定したユーザーだけがそのオブジェクトに書込むことができるロックである。書込みロックを使用すると、同一オブジェクトに対してアクセス・ロック以外は設定できない。

読込みロック・・・ SELECT文などの読込み操作の保全性を保つために使用されるロックである。読込みロックを使用すると、同一オブジェクトに対して複数のユーザーが読込みロックまたはアクセス・ロックを設定することができる。読込みロックが設定されているオブジェクトには書込み処理はできない。

アクセス・ロック・・・ 読込みまたは書込みを行うために既にロックされているオブジェクトを読込む場合に使用するロックである。アクセス・ロックによって読込むオブジェクトは書込み処理が許されるため、“ダーティ・リード”とも呼ばれる。内容が更新される可能性もあるため、多少のデータ不整合を問題としない場合に使用する。

それぞれのロック・レベルに対するタイプは、“LOCKING FOR”コマンドを明示的に使用することで変更できます(表3)。また、ロックの競合により要求を待機させたくない場合は、“NOWAIT”オプションを使うと、ロックが即座に取得できない場合にアボートさせることができます。

デッドロックとその回避策

デッドロックは交通渋滞に似ています。狭い道路で出会い頭に両側から自動車が進入してきた場合、どちらか一方が道という資源を譲らない限り先に進むことはできません。データベースのデッドロックは、トランザクションA が資源A をロックしてから資源B をロックする必要があり、トランザクションB が資源B を既にロックしていて、次に資源A をロックする必要がある場合に発生します(図2上段)。デッドロックは、通常の待ち行列によるロックの待機とは異なり、どちらか一方をアボートしない限り永遠に解決しない状態です。Teradataデータベースは、“疑似テーブル”という仕組みを用いることで殆どのデッドロックの発生を防いでいます(図2下段)。それでもデッドロックが発生してしまった場合は、Lock Manager が自動的に検知し、新しい方のトランザクションをアボートして資源を解放した後ロールバック ※2 を実行します。

まとめ

ロックはデータベースの整合性を保つ上で重要な機能です。ロックは LockManager によって制御され、SQL の種類に応じてレベルやタイプが自動的に設定されますが、LOCKING FORコマンドを使用することで明示的にタイプを変更することもできます。また、Teradataデータベースのロック処理では、“疑似テーブル”が自動的に用いられるためデッドロックは殆ど発生することはありませんが、アクセス・ロックや NOWAITオプションなどを適切に使うことで、不要なロック待ちによるトランザクションの遅延やデッドロックを避けることができます。通常のロック取得待ちによるトランザクションはタイムアウトすることはありませんが、デッドロックが検知された場合は、Lock Manager は新しいトランザクションをアボートしてロールバックを実行します。

  • *1: Data Manipulation Language の略で SQL におけるデータ操作言語のこと。主な DML文には、SELECT、INSERT、DELETE、UPDATE文が含まれる。

  • *2: ロールバックとは、不完全なデータベース・トランザクションを取り消す操作のこと。