トランザクションとは?
DBMSに対して複数のSQL文を送る場合に、1つ以上のSQL文をひとつの単位として扱うように指示することができます。
このひとつの単位のことを「トランザクション」というのです。
具体的には、次のようなイメージになります。
SELECT 〜 FROM テーブル名; ↓ UPDATE テーブル名 〜; ↓ ------------------ トランザクション ------------------ INSERT INTO テーブルアーカイブ 〜; ↓ DELETE テーブル名 〜; ------------------ トランザクション ------------------ ↓ SELECT 〜 FROM テーブルアーカイブ;
上記の例でいくと、「INSERT INTO文」と「DELETE文」がトランザクションです。
トランザクションが必要な場面
データベースで起こり得るトラブルには、「予期しない処理中断」「同時操作」が考えられます。
これらのトラブルによって、DBMSが処理を正しく完了できなかったり、テーブル内のデータの値がおかしくなってしまう可能性もあるでしょう。
また、電気トラブルによって一連のSQL処理が途中で途切れてしまう可能性もあるのです。
トランザクションは、このようなトラブルを想定して「複数の処理を連続して行う場合に、すべての処理が成功した場合だけデータベースへの変更を有効にする」場合に必要になります。
そのため、もし電気トラブルがあってもトランザクションを利用していれば、途中までの処理内容は反映されず、不正な値が入ったりなどの不正が防げます。
- トランザクションの途中で、処理が中断されないようにする
- トランザクションの途中に、他の人が割り込めないようにする
トランザクションの特性について
トランザクションはその処理の特徴から「ACID特性」と言われる特性を満たす必要があります。
ACID特性とは、次の4つの特性の頭文字をとった言葉です。
- 原子性 (ATOMICITY)
- 一貫性 (CONSISTENCY)
- 隔離性 (ISOLATION)
- 持続性 (DURABILITY)
それぞれの特性について解説します。
原子性 (ATOMICITY)
原子生とは、それ以上分割ができない「最小の作業単位」であることを意味する特性です。
もう少し具体的に説明をすると、トランザクションを構成している処理の結果がすべて「有効」になるか、「無効」になるかのどちらかだけになります。
先ほどの例で例えると、「INSERT INTO文」と「DELETE文」の両方の処理が完了するか、しないかです。
------------------ トランザクション ------------------ INSERT INTO テーブルアーカイブ 〜; ↓ DELETE テーブル名 〜; ------------------ トランザクション ------------------
「INSERT INTO文」だけ処理が完了し、「DELETE文」だけはできなかった、ということはありえないというわけですね。
一貫性 (CONSISTENCY)
一貫性は、その名前の通り、データの内容が一貫していることを表す特性です。
トランザクションで処理したデータが、実行前と実行後で整合性がとれている状態になっていなくてはいけません。
こちらも先ほどの例で言えば、「INSERT INTO文」でデータを挿入後、「DELETE文」を実行しているため、トランザクション完了後はテーブル内のデータが削除された状態が、生合成がとれている状態です。
それなのに、「INSERT INTO文」で挿入したデータが残っている状態などになっていると、一貫性が保たれていないということになります。
このような状態は、当然ながら起ってしまうと問題になるので、トランザクションの特性としてあげられるのです。
隔離性 (ISOLATION)
隔離性は、複数のトランザクションの処理対象がある1つのデータの場合に、それぞれのトランザクションは隔離された状態でデータの更新を行うという特性です。
例えば、次のようなトランザクションがあるとしましょう。
・トランザクション1:「INSERT INTO文」と「DELETE文」を実行
・トランザクション2:「SELECT FROM文」と「UPDATE文」を実行
これらのトランザクションが同じデータに対して実行される時、トランザクション1を実行している途中で、トランザクション2を実行することは認められないということになります。
つまり、必ず「トランザクション1→トランザクション2」の順番か「トランザクション2→トランザクション1」の順番で処理が実行されることになります。
当たり前ですが、同時に処理を実行しようとした場合、予期せぬ動作やエラーが発生する原因になるため、このような特性を採用しているのです。
持続性 (DURABILITY)
持続性は、その名前の通りトランザクションで処理するデータは、トランザクションの処理が終わるまで変わらない状態を意味する特性です。
トランザクションの実行中に、処理するデータが変わってしまっては不具合やバグを生み出すことにつながります。
そのため、トランザクションが終了するまで、データの状態は変わりません。
トランザクションの書き方
トランザクションを実行するにはどのように記述すればよいですか?
トランザクションを使うためには「BEGIN」「COMMIT」「ROLLBACK」の記述が必要です。サンプルを見ながら書き方を学びましょう!
トランザクションを指定するには、「複数のSQL文のどの範囲が1つのトランザクションであるか」を明示することでDBMSが制御してくれます。
具体的には、次の3つのSQL文を使います。
SQL文 | 詳細 |
---|---|
BEGIN | トランザクション開始の指示です。 BEGIN以降に書かれたSQL文を、1つのトランザクションとします。 |
COMMIT | トランザクション終了の指示です。 COMMIT以前に書かれたSQL文を、1つのトランザクションとし、変更を確定します。 |
ROLLBACK | トランザクション終了の指示です。 ROLLBACK以前に書かれたSQL文を、1つのトランザクションとし、変更の取り消しをします。 |
トランザクション開始の指示は「BEGIN」だけですが、終了の仕方には「COMMIT」と「ROLLBACK」があるので覚えておきましょう。
例えば、従業員のデータを扱う 従業員テーブル の2020年8月以前のデータをバックアップテーブルに移動させる、といった処理をトランザクションで行ってみます。
SQL文は次のように記述しましょう。
BEGIN; -- バックアップテーブルにコピー INSERT INTO 従業員バックアップ SELECT * FROM 従業員テーブル WHERE 日付 <= ‘2020-08-31’; -- 従業員テーブルからデリート DELETE FROM 従業員テーブル WHERE 日付 <= ‘2020-08-31’; COMMIT;
上記のSQLを実行することで、「バックアップテーブルにコピー」と「従業員テーブルからデリート」は不可分なものとして扱われます。
万が一、バックアップテーブルにコピーした後にトラブルが発生しても、自動的にロールバックが行われて、「バックアップテーブルにコピー」は取り消されます。
また、 ROLLBACK のSQL文を実行することで、明示的にロールバックを行うことも可能です。
自動コミットモード
各DBMS付属のSQL実行ツールを使用している場合、ロールバックができないことがあります。
これは、多くのSQL実行ツールが「自動コミットモード」と呼ばれるモードをデフォルトで設定しているからです。
このモードが設定されていると、DBMSは1つのSQL文が実行されるたびに、裏側で自動的にコミットを実行してしまいます。
そのため、トランザクションをロールバックできない状況が生まれるのです。
DBMSによっては、自動コミットモード中であっても「BEGIN」を実行すれば、コミットかロールバックのまでの間は一時的に自動コミットを解除できます。
この自動コミットモードを解除する方法は、ツールや環境によって異なるので確認が必要です。
例えば、MySQLであれば「SET AUTOCOMMIT=0」というSQL文になります。
トランザクションの分離
DBMSに対して、複数の利用者が同時に処理を実行すると発生し得る副作用には次の3つが挙げられます。
副作用 | 詳細 |
---|---|
ダーティーリード | まだコミットしていない変更を他の人が読めてしまうという現象です。 未確定の情報・データをもとに処理を行ってしまう可能性があるので、とても危険な副作用と言えます。 |
反復不能読み取り | あるテーブルに対してSELECT文を実行した後、他の人がUPDATE文でデータを書き換えた場合、次にSELECT文を実行した際に検索結果が異なるものになってしまう副作用です。 データの整合性が崩れてしまう原因になります。 |
ファントムリード | 2回目のSELECT文を実行する間に、他の人がINSERT INTO文でデータを追加すると、検索結果が異なるものになってしまう副作用です。 反復不能読み取りと同じ理由で危険な副作用と言えます。 |
このようにDBMSの扱いは、複数人で行うほどデータの整合性を保つことが難しく、情報の錯綜につながりかねません。
上記の副作用を解決するためにも、トランザクションは有効な手段です。
なぜなら、DBMSはそれぞれのトランザクションについて分離性を維持しているからです。
3つの副作用のような影響を受けないために、トランザクションを実行する際は分離して実行します。
仮に、トランザクション1とトランザクション2を同時に実行していても、単独で実行しているのと同じ結果となるように制御しているのです。
まとめ
SQLのトランザクションについて解説しました。
データを正しく、安全に扱うためにトランザクションの利用は有効です。
特に、複数人で利用することが想定される場合は、積極的に活用を検討してみるとよいでしょう。
ぜひこの記事を参考に、トランザクションの理解を深めてください!