基本情報技術者 PR

【基本情報】関係データベースの排他制御について解説

記事内に商品プロモーションを含む場合があります

●この記事で学べること
・排他制御
・専有ロックと共有ロック
・デッドロック

トランザクション処理

データベースに対して処理を行う際、まとめて行う必要がある処理を一括りにして行う必要があり、この一連の処理をトランザクション処理と言います。トランザクション処理は他のトランザクション処理に影響を受けてはならないという「独立性」を満たす必要があります。

下の記事で詳しく解説しているので、トランザクション処理について不安がある人は先にこちらを参考にしてください。

【基本情報】トランザクション処理について解説この記事ではトランザクション処理について解説しています。 トランザクション処理のACID特性やコミット/ロールバックについても解説しています。【令和5年度問7】【令和元年度秋期問28】【平成29年度秋期問29】【平成28年度春期問28】も解説しています。...

排他制御

トランザクション処理ではおかしなデータを作成しないように独立性を満たす必要があります。そのため、トランザクション処理を行っている時は別のトランザクション処理が実行出来ないようにデータベースをロックします。これを排他制御と言います。

排他制御をしないとどうなるのか

排他制御を行わずに、複数のトランザクション処理を行うとどうなるのでしょうか。ATMからお金を引き出すトランザクションを同時に行った場合を考えてみます。

ATMからお金を引き出すトランザクションでは以下3つの処理を行います。

  1. 口座残高を確認する
  2. 口座残高からお金を減らす
  3. ATMからお金を出金する

今、残高が100万円の口座から1万円を引き出す操作を同時に行ってみます。

  1. トランザクション①が残高を確認する:残高100万円であると確認
  2. トランザクション②が残高を確認する:残高100万円であると確認
  3. トランザクション①で残高を1万円減らす:100万円から1万円減らして99万円にする
  4. トランザクション②で残高を1万円減らす:100万円から1万円減らして99万円にする
  5. トランザクション①で1万円を出金
  6. トランザクション②で1万円を出金

トランザクション①と②で合計2万円出金しているのに銀行の残高は99万円と、おかしなデータが発生しています。

排他制御をするとどうなるか

排他制御を行うと、トランザクション実行中はデータベースをロックして別のトランザクションがアクセス出来ないようにします。

  1. トランザクション①が残高を確認する:残高100万円であると確認
  2. トランザクション①で残高を1万円減らす:100万円から1万円減らして99万円にする
  3. トランザクション①で1万円を出金
  4. トランザクション②が残高を確認する:残高99万円であると確認
  5. トランザクション②で残高を1万円減らす:99万円から1万円減らして98万円にする
  6. トランザクション②で1万円を出金

トランザクション①実行中はデータベースをロックしているので、トランザクション②はデータベースにアクセス出来ません。そのため、トランザクション①→トランザクション②の順番で実行することになり、データの整合性が保たれます。

専有ロックと共有ロック

データベースにおかしなデータを生み出さないためには排他制御をする必要があることが分かりました。では、排他制御の際、どのようにデータベースをロックするのでしょうか。

ロックの方法はトランザクション処理のタイプによります。

2種類のトランザクション処理

トランザクション処理には大きく分けて2種類あります。

  1. 登録・更新・削除など、データを変更する処理
  2. データを変更せずに読み取るだけの処理

口座への入金や出金はデータを変更する処理ですが、残高や取引履歴を確認するのは読み取り処理になります。

トランザクション処理の種類によって、排他制御のロックの仕方が変わります。

専有ロック

データを変更する処理の場合は専有ロックを行います。

専有ロックを行うと、後続のトランザクションはデータを変更する処理もデータを読み取る処理も行えません。

データ変更中に別のトランザクション処理がデータを変更するとおかしなデータが出来てしまいます。また、データを読取っても変更中のデータを読取ることになるので誤解を生む可能性があります。なので、専有ロック中は変更も読取も不可になります。

共有ロック

データを読取る処理の場合は共有ロックを行います。

共有ロックを行うと、後続のトランザクションはデータを変更する処理は出来ませんが、データを読み取る処理は行えます。

データ読取中に別のトランザクション処理がデータを変更すると、変更中のおかしなデータを見ることになってしまいます。しかし、データ読取中に別のトランザクションがデータを読取る分にはデータの不整合は発生しないので問題ありません。なので、共有ロック中は変更不可で読取可能になります。

デッドロック

デッドロックとは、複数のトランザクション処理が同じデータベースを使用する場合に、お互いに相手がアクセスしたいデータベースをロックしてしまい、永遠に待ち状態になってしまう状態のことです。

下の例では、トランザクション①がテーブルA→テーブルBの順番で、トランザクション②がテーブルB→テーブルAの順番で編集しようとしているため、お互いがお互いロックしているテーブルの解放待ちになってしまい、次のステップに進めなくなっています。この状態がデッドロックです。

アクセスする順番が逆のトランザクション処理が存在すると、デッドロックが発生する可能性があるため、複数のトランザクション処理を実行する場合は同じ順番でアクセスするように設計します。

基本情報技術者試験での出題例

令和元年度秋期問29

基本情報技術者
午前試験 令和元年度秋期問29

2相ロッキングプロトコルに従ってロックを獲得するトランザクションA,Bを図のように同時実行した場合に,デッドロックが発生しないデータ処理順序はどれか。ここで,read と update の位置は,アプリケーションプログラムでの命令発行時点を表す。また,データWへの read は共有ロックを要求し,データX,Y,Zへの update は各データへの専有ロックを要求する。

正解と解説

正解は”ウ”

データWへのアクセスは共有ロックを要求するため、ここでデッドロックは発生しません。
なので、データX,Y,Zへの専有ロックでデッドロックが起こらないパターンを考えます。

専有ロックは同じ順番でアクセスすれば起こりません。トランザクションAと同じ順番でデータにアクセスしているのは選択肢ウなのでウが正解です。

平成30年度秋期問29

基本情報技術者
午前試験 平成30年度秋期問29

ロックの粒度に関する説明のうち,適切なものはどれか。

ア データを更新するときに,粒度を大きくすると,他のトランザクションの待ちが多くなり,全体のスループットが低下する。

イ 同一のデータを更新するトランザクション数が多いときに,粒度を大きくすると,同時実行できるトランザクション数が増える。

ウ 表の全データを参照するときに,粒度を大きくすると,他のトランザクションのデータ参照を妨げないようにできる。

エ 粒度を大きくすると,含まれるデータ数が多くなるので,一つのトランザクションでかけるロックの個数が多くなる。

正解と解説

正解は”ア”

ロックの粒度とは、トランザクション実行時にどこまでロックするかを決める単位です。
編集対象の行だけロックするのか、表ごとロックするのか、データベースごとロックするのかを決めます。

ア スループットとは処理時間のことです。1つのトランザクションがロックするものが大きいと、他のトランザクションの待ちが長くなるため、スループットは低下します。

イ ロックの対象を増やすと、同時実行できるトランザクションは減少します。

ウ ロックの粒度を大きくすると、他のトランザクションの妨げになります。

エ 1つ1つのトランザクションのロックの粒度を大きくすると、同時実行出来るトランザクションは減るため、ロックの数自体は少なくなります。

平成30年度春期問30

基本情報技術者
午前試験 平成30年度春期問30

RDBMSのロックの粒度に関する次の記述において,a,bの組合せとして適切なものはどれか。

並行に処理される2つのトランザクションがそれぞれ一つの表内の複数の行を更新する。行単位のロックを使用する場合と表単位のロックを使用する場合とを比べると,ロックの競合がより起こりやすいのは『 a 』単位のロックを使用する場合である。また,トランザクション実行中にロックを管理するためのRDBMSのメモリ使用領域がより多く必要になるのは『 b 』単位のロックを使用する場合である。

正解と解説

正解は”ウ”

トランザクション処理を実行する際、ロックをする対象が大きければ大きいほど、他のトランザクション処理の待ちが発生しやすくなります。これをロックの競合と言います。

表と行では、表の方が大きい単位になるので、表単位のロックを使用した場合の方がロックの競合は発生しやすくなります。

しかし、複数行を編集するようなトランザクション処理を実行する場合、行1つ1つをロックするのと、複数行全部を含む表を一括でロックするのを比べると、表を一括でロックする方がロジックが単純です。なので、ロックを管理するために必要なメモリも少なくて済みます。

関連記事