Oracle Databaseでは、トランザクション中に行った変更を取り消すためにROLLBACK(ロールバック)を使用できます。例えば、UPDATE文で誤った値に更新してしまっても、その変更をまだCOMMITしていなければ、ROLLBACKによって原則としてトランザクション開始前の状態へ戻すことができます。
ただし、「OracleならROLLBACKすればいつでも元に戻せる」という理解は正しくありません。COMMIT済みの変更は通常のROLLBACKでは取り消せず、DDLによる暗黙的なCOMMITなどにも注意が必要です。また、SAVEPOINTを利用すればトランザクション全体ではなく途中まで戻すこともできます。
この記事では、Oracle DatabaseにおけるROLLBACKの仕組みを、UPDATE・INSERT・DELETEの具体例やCOMMIT、SAVEPOINTとの関係を含めて解説します。
- Oracle DatabaseではROLLBACKで未確定の変更を取り消せる
- UPDATEをROLLBACKする具体例
- INSERTやDELETEもROLLBACKできる
- ROLLBACKするとトランザクション内の変更が取り消される
- COMMITした後は通常のROLLBACKでは戻せない
- SAVEPOINTを使えばトランザクションの途中まで戻せる
- ROLLBACKとROLLBACK TO SAVEPOINTの違い
- DDLでは暗黙的なCOMMITに注意する
- SQLツールやアプリの自動COMMITにも注意
- COMMIT後の誤更新はどうすればよい?
- ROLLBACKはバックアップの代わりにはならない
- 誤更新を防ぐために実務で意識したいポイント
- まとめ:OracleのROLLBACKは「COMMIT前の変更を取り消す」が基本
Oracle DatabaseではROLLBACKで未確定の変更を取り消せる
Oracle DatabaseのROLLBACK文は、現在のトランザクションで行った未確定の変更を取り消すためのSQL文です。Oracle公式ドキュメントでも、ROLLBACKは現在のトランザクションで実行した作業を取り消すために使用すると説明されています。[参照] Oracle Database SQL Language Reference「ROLLBACK」
例えば社員テーブルの給与を更新したものの、WHERE条件を間違えていたことに気付いたとします。まだCOMMITしていなければ、ROLLBACKを実行することで、そのトランザクションによる更新を取り消せます。
この仕組みがあるため、OracleではINSERT、UPDATE、DELETEなどのDMLを実行した瞬間に、その変更が無条件で永久確定するわけではありません。トランザクションを確定するCOMMITと、取り消すROLLBACKを理解することが重要です。
UPDATEをROLLBACKする具体例
例えば、EMPLOYEESという表のemployee_idが100の従業員について、給与を500000へ変更するとします。次のようなUPDATEを実行したと考えます。
UPDATE employees SET salary = 500000 WHERE employee_id = 100;
実行後に「本当はemployee_id=101を変更する予定だった」と気付いた場合、まだCOMMITしていなければ次のSQLを実行します。
ROLLBACK;
これにより、そのトランザクションで行われた未確定の変更が取り消されます。つまり、UPDATE直後であってもCOMMIT前なら修正できる余地があります。
INSERTやDELETEもROLLBACKできる
ROLLBACKの対象はUPDATEだけではありません。通常のトランザクションで実行したINSERTやDELETEについても、COMMIT前であれば取り消すことができます。
例えば、誤って次のDELETEを実行したとします。
DELETE FROM employees WHERE department_id = 50;
削除対象を確認して「削除してはいけないデータだった」と気付いた場合、COMMIT前ならROLLBACK;を実行することで、そのトランザクションによる削除を取り消せます。
INSERTの場合も同様です。誤ったデータを追加したあとCOMMITしていなければROLLBACKできます。このため重要な更新作業では、変更件数や内容を確認してからCOMMITする運用が重要になります。
ROLLBACKするとトランザクション内の変更が取り消される
注意したいのは、単純なROLLBACK;は「直前のSQL文だけを1個取り消すボタン」ではないという点です。現在のトランザクションで行った未確定の変更を取り消します。
例えば同じトランザクションでUPDATE、INSERT、DELETEを順番に実行し、その後に通常のROLLBACKを実行すると、それらの未確定の変更がまとめて取り消されることがあります。
「最後のUPDATEだけ戻して、その前のINSERTは残したい」といった細かな制御をしたい場合には、後述するSAVEPOINTを利用する方法があります。
COMMITした後は通常のROLLBACKでは戻せない
ROLLBACKを理解するうえで最も重要なのがCOMMITとの関係です。COMMITは現在のトランザクションの変更を確定する操作です。Oracle公式ドキュメントでは、COMMITによって現在のトランザクションを終了し、すべての変更を永続化すると説明されています。[参照] Oracle Database SQL Language Reference「COMMIT」
例えば次の順番でSQLを実行したとします。
UPDATE employees SET salary = 500000 WHERE employee_id = 100;COMMIT;ROLLBACK;
この場合、UPDATEによる変更はCOMMITによってすでに確定しています。その後にROLLBACKを実行しても、通常のROLLBACKでそのUPDATEをCOMMIT前の状態へ戻すことはできません。
したがって、「間違えたら後でROLLBACKすればいい」と考えて先にCOMMITするのは危険です。COMMITは内容を確認したうえで実行する必要があります。
SAVEPOINTを使えばトランザクションの途中まで戻せる
トランザクション全体を取り消したくない場合に利用できるのがSAVEPOINTです。SAVEPOINTによってトランザクション内に目印を設定し、ROLLBACK TO SAVEPOINTを使ってその地点まで戻すことができます。[参照] Oracle Database SQL Language Reference「SAVEPOINT」
例えば次のような流れを考えます。
UPDATE employees SET salary = 300000 WHERE employee_id = 100;SAVEPOINT point_a;UPDATE employees SET salary = 400000 WHERE employee_id = 101;ROLLBACK TO SAVEPOINT point_a;
この場合、SAVEPOINT設定後に行ったemployee_id=101への変更を取り消しつつ、SAVEPOINTより前に行ったemployee_id=100への変更をトランザクション内に残す、といった制御が可能です。
ただし、SAVEPOINTはCOMMITをまたいで過去へ戻るための機能ではありません。COMMITするとトランザクションが終了し、そのトランザクションのSAVEPOINTも消去されます。
ROLLBACKとROLLBACK TO SAVEPOINTの違い
両者は似ていますが、取り消す範囲が異なります。通常のROLLBACKは現在のトランザクション全体を終了させて未確定の変更を取り消すのに対し、ROLLBACK TO SAVEPOINTは指定したSAVEPOINT以降の変更を取り消し、トランザクション自体は継続できます。
| 操作 | 主な意味 |
|---|---|
ROLLBACK; |
現在のトランザクションの未確定変更を取り消す |
SAVEPOINT sp1; |
トランザクション途中に戻り先を設定する |
ROLLBACK TO SAVEPOINT sp1; |
sp1より後の変更を取り消す |
COMMIT; |
現在のトランザクションの変更を確定する |
複数の更新処理を一つのトランザクションで行う場合は、SAVEPOINTを適切に利用することで、処理全体をやり直さず一部分だけ戻せる場合があります。
DDLでは暗黙的なCOMMITに注意する
Oracle Databaseでは、CREATE、ALTER、DROPなどのDDLを扱うときに特に注意が必要です。Oracleでは多くのDDL文について、実行前に暗黙的なCOMMITが発生します。また、正常に完了したDDLの後にもCOMMITが行われます。[参照] Oracle Database SQL Language Reference「COMMIT」
例えばUPDATEを実行したあと、明示的なCOMMITをしていないからまだROLLBACKできると思っていても、その後にDDLを実行したことで先行するトランザクションが暗黙的にCOMMITされるケースがあります。
このため、Oracleのトランザクションを扱う際には「自分でCOMMITと入力したか」だけを見るのでは不十分です。使用しているSQL文やツール、アプリケーションのトランザクション制御まで確認する必要があります。
SQLツールやアプリの自動COMMITにも注意
データベース側の仕組みだけでなく、利用しているクライアントツールやアプリケーションの設定にも注意が必要です。環境によっては自動的にCOMMITする設定や、処理終了時にCOMMITする実装になっている場合があります。
例えば「UPDATEした直後だからROLLBACKできるはず」と考えていても、使用しているプログラムがUPDATE後すぐにCOMMITしていれば、その変更を通常のROLLBACKで戻すことはできません。
本番データを変更するときは、SQLそのものだけでなく、どのタイミングでトランザクションが開始・終了し、どこでCOMMITされる設計なのかを把握しておくことが重要です。
COMMIT後の誤更新はどうすればよい?
COMMIT後は通常のROLLBACKでは戻せませんが、それが「Oracleでは絶対に復旧不可能」という意味ではありません。状況や構成によっては、Flashback機能、バックアップやリカバリ、変更履歴などを利用して過去の状態を確認・復旧できる可能性があります。
例えばOracle DatabaseにはFlashback Queryがあり、UNDO情報が利用できる範囲で、過去のある時点におけるデータを問い合わせることができます。またFlashback Tableなど、目的に応じた複数のFlashback機能があります。[参照] Oracle Database Development Guide「Using Oracle Flashback Technology」
ただし、Flashbackを使えばどんな誤操作でも必ず復元できるわけではありません。UNDOの保持状況、権限、設定、対象オブジェクト、経過時間、利用するFlashback機能などによって可否が変わります。本番環境で誤更新をCOMMITしてしまった場合は、慌てて追加UPDATEを実行せず、DBAやシステム管理者へ連絡して復旧方針を決めるのが安全です。
ROLLBACKはバックアップの代わりにはならない
ROLLBACKはトランザクション制御の機能であり、障害対策用バックアップとは目的が異なります。「ROLLBACKがあるからバックアップはいらない」という考え方は危険です。
ROLLBACKが特に有効なのは、まだ確定していないトランザクションを取り消す場面です。一方、すでにCOMMITされたデータの復旧、ストレージ障害、データファイルの損失などは、通常のROLLBACKとは別の領域になります。
そのため実運用では、トランザクション制御に加えて、適切なバックアップ・リカバリ設計、監査・変更管理、必要に応じたFlashback機能などを組み合わせることが重要です。
誤更新を防ぐために実務で意識したいポイント
ROLLBACKできるからといって、UPDATEやDELETEを無警戒に実行してよいわけではありません。特に本番環境では、WHERE句を間違えると想定以上の行が更新・削除される危険があります。
例えば大量更新を行う前に、同じWHERE条件を使ったSELECTで対象行を確認する方法があります。対象が10行の予定なのにSELECTで10万行返ってきたなら、UPDATEを実行する前に条件の誤りへ気付けます。
また、重要な作業では作業手順や復旧手順を事前に準備し、COMMIT前に変更件数・内容を確認します。本番環境では組織の運用ルールや承認手順を優先し、独断で変更・復旧を行わないことも重要です。
まとめ:OracleのROLLBACKは「COMMIT前の変更を取り消す」が基本
Oracle Databaseでは、ROLLBACKによって現在のトランザクションで行った未確定の変更を取り消すことができます。UPDATEだけでなく、INSERTやDELETEなどのDMLによる変更も、通常はCOMMIT前であればROLLBACKの対象になります。
一方、COMMITによって確定した変更を、後から通常のROLLBACKで元に戻すことはできません。またDDLによる暗黙的COMMITや、利用しているツール・アプリケーション側の自動COMMITにも注意が必要です。
トランザクションの途中だけを戻したい場合にはSAVEPOINTとROLLBACK TO SAVEPOINTを利用できます。COMMIT後の誤更新については、通常のROLLBACKではなくFlashbackやバックアップ・リカバリなど別の方法を検討することになります。
OracleのROLLBACKを理解するときは、「ROLLBACK=いつでも過去へ戻せる機能」ではなく、「まだ確定していないトランザクションを取り消すための機能」と覚えておくと、COMMITやSAVEPOINTとの違いも理解しやすくなります。


コメント