【SQL入門】トランザクションの概要
はじめに
『スッキリわかるSQL入門 第2版』を読んで、問題に取り組みつつ、メモとしてまとめました。
なお、一部SQL文の例などを引用させていただいています。
トランザクション(transaction)
データベースにおいて一連の処理をまとめて1つの単位として扱う仕組みのこと。
DBMSに対して複数のSQLを送る場合に、1つ以上のSQL文をひとかたまりとして扱うよう指示することができます(トランザクション制御 transaction control)。
これにより、処理全体が成功するか、あるいは失敗して元に戻るかのどちらかになり、データの整合性が保たれます。
※ https://well-field.co.jp/services/education/web-text/sql-mysql/sql-v28 より画像引用
◎DBMSによるトランザクション制御(1)
- トランザクションの途中で、処理が中断されないようにする
- トランザクションの途中に、他の人の処理が割り込めないようにする
コミットとロールバック
トランザクションの中断
振り込み処理の例
振り込み処理を実現するために必要なこと
① 振込元の口座残高を減らす
② 振込先の口座残高を増やす
ここで、①が完了したあと、異常停止によって処理が中断してしまうと、振込元の口座残高が減るだけで、振込先のお金が増えない事態になってしまいます。
2つのUPDATE文を1つのトランザクション(1つの処理のまとまり)として扱うようにDBMSに指示することで、この問題を解決することができます。
DBMSは、どんな非常時であっても、トランザクションを「一部だけが実行されることはあってはならない、途中で分割不可能なもの」として取り扱う
◎DBMSによるトランザクション制御(2)
DBMSは、トランザクションに含まれるすべてのSQL文について、必ず
「すべての実行が完了している」または「1つも実行されていない」
のどちらかの状態になるように制御する
原始性(atomicity)
トランザクションに含まれる複数のSQL文が、DBMSによって不可分なものとして扱われる性質のこと。
トランザクションは、複数のSQL文(例:UPDATEやINSERT)をひとまとめにした論理的な処理単位です。この単位を不可分(分割できない、すべて実行されるか、あるいは何も実行されないかのどちらか)として扱う性質が原子性です。
原始性確保の仕組み
コミット(commit)
トランザクション中のSQL文によってテーブルのデータが書き換えられると、それは確定ではなく仮のものとして管理されます。
そして、トランザクションが終了する際に、これらの「仮の書き換え」をすべて確定したことにします。
※ https://well-field.co.jp/services/education/web-text/sql-mysql/sql-v28 より画像引用
ロールバック(rollback)
トランザクション中に異常が発生して中断した場合、DBMSはそれまで行なったすべての仮の書き換えをキャンセルして、「なかったこと」にする動作のこと。
トランザクション内のそれまでの変更をすべて取り消し、トランザクションが開始される前の状態にデータベースを戻す処理のことを指します。
※ https://well-field.co.jp/services/education/web-text/sql-mysql/sql-v28 より画像引用
SQL文のエラーで失敗したり、明示的にキャンセルが指示された場合などに行われる。
電源が落ちて突然処理が中断した場合も、再びデータベースを起動した際に自動的にロールバックが行われます。
トランザクションの指定方法
DBMSにどの範囲が1つのトランザクションであるかを伝えることで制御される。
トランザクションを使うための指示
BEGIN : 開始の指示
この指示以降のSQL文を1つのトランザクションとする。
COMMIT : 終了の指示
この指示までを1つのトランザクションとし、変更を確定する。
ROLLBACK : 終了の指示
この指示までを1つのトランザクションとし、変更の取り消しをする。
BEGIN;
-- 処理1: アーカイブテーブルへコピー
INSERT INTO 家計簿アーカイブ
SELECT *
FROM 家計簿
WHERE 日付 <= '2024-01-31';
-- 処理2: 家計簿テーブルから削除
DELETE FROM 家計簿
WHERE 日付 <= '2024-01-31';
COMMIT;
これにより、処理1と処理2を不可分なものとして扱います。
仮に、処理1の後に障害が発生した場合、自動的にロールバックが行われ、処理1の実行が取り消されます。
自動コミットモードの解除
自動コミットモード(auto commit mode)
通常、トランザクションは BEGIN TRANSACTION
で開始し、COMMIT
または ROLLBACK
で明示的に終了させる必要があります。しかし、自動コミットモードが有効な場合、このプロセスは自動化されます。
(例)トランザクション = INSERT文 + UPDATE文
INSERT文を実行: このSQL文が成功すると、その時点で自動的にコミットされる
UPDATE文を実行: このSQL文が成功すると、その時点で自動的にコミットされる
これにより、ユーザーは明示的なコミットを意識することなく、個々のSQL文の変更を確定させることができます。
自動コミットモードで動作しているとき、DBMSは1つのSQL文が実行されるたびに、自動的に裏でコミットを実行している。
DBMSによっては、デフォルト状態では自動コミットモードで動作しています。
また、DBMSによって、自動コミットモード中であっても BEGIN
を実行することで、コミットかロールバックまでの間、一時的に自動コミットを解除することができます。
自動コミットモードは、トランザクションが明示的に開始されていない場合のデフォルトの動作であり、トランザクションを開始することでこの動作は一時的に上書きされます。
多くのデータベースでは、BEGIN TRANSACTION
(または同等のコマンド)を実行して明示的にトランザクションを開始すると、自動コミットモードは一時的に無効になります。
通常時(自動コミットモードが有効)
INSERT文やUPDATE文を1つ実行するたびに、その変更が自動的にコミットされます。
トランザクション開始後
BEGIN TRANSACTION
を実行すると、この状態が解除されます。
その後、複数のSQL文(例:UPDATEやINSERT)を実行しても、それらは単一のトランザクションとして扱われ、自動的にコミットされることはありません。
トランザクション終了
すべての処理が成功したらCOMMITを実行して変更を永続化し、失敗したらROLLBACKを実行して変更を破棄します。この時点で、再び自動コミットモードに戻るのが一般的です。
参考文献
『スッキリわかるSQL入門 第2版』
Discussion