Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Transactions, Deadlocks & Log Based Recovery in SQL

2025年10月03日に「Dev.to」が公開したITニュース「Transactions, Deadlocks & Log Based Recovery in SQL」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

「オールオアナッシング」で部分更新を防ぐのがトランザクション。互いのリソースを待ち合い停止するデッドロックはデータベースが解決する。変更履歴を記録し、障害からのデータ復旧を可能にするのがログベースリカバリだ。

ITニュース解説

データベースを扱うシステムエンジニアにとって、データの正確さと信頼性を保つことは非常に重要だ。特に、複数の人が同時にデータベースを利用したり、予期せぬシステム障害が発生したりする状況では、データが一貫した状態を維持できるよう、特別な仕組みが必要になる。今回解説するのは、データベースの信頼性を支える三つの重要な概念、すなわち「トランザクション」「デッドロック」「ログベースリカバリ」だ。これらを理解することで、データベースがどのように安全に動作しているのか、その基盤が見えてくるだろう。

まず「トランザクション」について説明する。トランザクションとは、データベース上で行われる一連の処理をひとまとまりの作業として扱う仕組みだ。このひとまとまりの作業は「アトミック性」と呼ばれる特性を持つ。アトミック性とは「全か無か」を意味し、トランザクション内のすべての処理が成功して初めてその変更が確定(コミット)されるか、そうでなければすべての変更がなかったことに戻される(ロールバック)か、どちらか一方しか起こらないことを保証する。途中で処理が失敗した場合や、利用者が意図的に操作を取り消したい場合でも、データが中途半端な状態になるのを防ぐのだ。

例えば、架空の銀行口座を管理するAccountsというテーブルを考える。このテーブルには、口座番号、名前、残高の三つの情報が格納されている。初期状態として、アリスの口座に1000、ボブの口座に1500、チャーリーの口座に2000がそれぞれ入っているとする。ここで、アリスからボブへ500を送金する処理を考えてみよう。この処理は、アリスの残高から500を減らし、ボブの残高に500を加えるという二つのステップから成る。もしアリスの残高を減らした後にシステムが停止したり、ボブの残高を増やす処理が何らかの理由で失敗したりしたらどうなるだろうか。アリスの残高だけが減り、ボブの残高は増えないままとなり、合計金額が合わなくなってしまう。このようなデータの不整合を防ぐのがトランザクションだ。

送金処理をトランザクションとして開始するには、START TRANSACTIONという命令を使用する。次に、アリスの残高を500減らすSQL文を実行し、続いてボブの残高を500増やすSQL文を実行する。これらの操作の途中で、現在の口座残高を確認すると、アリスが500、ボブが2000になっているのが確認できるだろう。しかし、この時点ではまだデータベースへの変更は一時的なもので、確定はされていない。ここで、もし送金を取りやめたいと判断したり、何らかの問題が発生したりした場合、ROLLBACKという命令を実行することで、トランザクション開始前の状態に戻すことができる。ROLLBACKを実行した後で再度口座残高を確認すると、アリスは1000、ボブは1500という元の状態に戻っていることがわかる。このように、ROLLBACKによって部分的な更新が発生せず、データベースの一貫性が保たれるのがアトミック性の重要な側面だ。すべての処理が問題なく完了した場合は、COMMITという命令で変更を確定する。

次に「デッドロック」について解説する。デッドロックとは、複数のトランザクションが互いに相手が保持しているリソース(例えば、データベースの特定の行やテーブルなど)の解放を待ち続け、結果としてどのトランザクションも処理を進められなくなる膠着状態のことだ。

このデッドロックがどのように発生するかを、二つの異なるセッション(利用者がデータベースに接続している状態)を使った例で見てみよう。両方のセッションが同時にトランザクションを開始する。セッション1がまず、ボブの口座から50を引くという更新処理を実行すると、この処理によってボブの口座データがロックされる。同時に、セッション2はアリスの口座から50を引くという更新処理を実行し、アリスの口座データをロックする。ここまでは問題ない。しかし、次にセッション1がアリスの口座に50を加える更新処理を実行しようとすると、アリスの口座はセッション2によってロックされているため、セッション1はセッション2がロックを解除するのを待つ状態になる。一方で、セッション2もボブの口座に50を加える更新処理を実行しようとすると、ボブの口座はセッション1によってロックされているため、セッション2はセッション1がロックを解除するのを待つ状態になる。結果として、セッション1はセッション2を待ち、セッション2はセッション1を待つという、誰も先に進めないデッドロック状態に陥る。

現代のデータベースシステムは、このようなデッドロックを自動的に検出し、解消する機能を持っている。データベースは、デッドロックが発生したことを検知すると、どちらか一方のトランザクションを「犠牲者」として選び、強制的にそのトランザクションを終了させ、ロールバックする。これにより、もう一方のトランザクションはロックが解除されたリソースを利用できるようになり、処理を続行できる。デッドロックはシステム全体を停止させる可能性があるため、データベースがこれを自動で解決する仕組みは、システムの安定稼働にとって非常に重要だ。

最後に「ログベースリカバリ」について説明する。データベースは、システムが予期せずクラッシュしたり、電源が落ちたりといった障害が発生した場合でも、データの整合性と耐久性(変更が失われないこと)を保証する必要がある。このために利用されるのが「ログ」だ。データベースは、発生するすべての変更操作(データの追加、更新、削除など)を詳細に記録したログを保持している。これは、MySQLのバイナリログやPostgreSQLのWAL(Write-Ahead Log)などと呼ばれるものだ。

例えば、チャーリーの口座残高に200を加えるトランザクションを開始し、実際に残高を更新するSQL文を実行した後、ROLLBACKでそのトランザクションを取り消したケースを考えてみよう。この場合、チャーリーの口座残高は元の状態に戻る。しかし、データベースのログには、残高を更新したという操作と、その更新を取り消したという操作の両方が記録される。これは非常に重要だ。なぜなら、もしシステムがクラッシュした場合、データベースは最後に記録されたログを参照して、どこまで処理が進んでいたのかを正確に把握できるからだ。

システムがクラッシュから復旧する際、データベースはこのログを読み込む。そして、ログに記録されているトランザクションの中で、障害発生前にすでにコミットされていた(確定済みだった)ものについては、もしその変更がデータファイルに完全に書き込まれていなかったとしても、ログ情報に基づいてその変更を再度適用する(REDO操作)。一方、障害発生時にまだコミットされていなかった(未確定だった)トランザクションについては、その変更をすべて取り消し、トランザクション開始前の状態に戻す(UNDO操作)。これにより、たとえシステムが不意に停止したとしても、データベースは常に一貫性のある状態に復元され、コミットされたデータは失われず、未コミットのデータはきれいに取り消されることが保証される。このログベースリカバリの仕組みが、データベースの耐久性を支える根幹となっている。

これらの「トランザクション」「デッドロック」「ログベースリカバリ」という三つの概念は、現代のデータベースシステムが持つ高度な信頼性と堅牢性を理解する上で欠かせないものだ。トランザクションがデータの整合性を「全か無か」で保証し、デッドロック管理が複数の利用者による並行処理の衝突を解決し、そしてログベースリカバリがシステム障害からの安全な復旧を可能にする。これらすべてが連携し、システムエンジニアが構築するアプリケーションが信頼できるデータ基盤の上で動作することを可能にしているのだ。

関連コンテンツ

関連IT用語