Oracle トランザクションの基礎:COMMIT・ROLLBACKとセーブポイント

Oracle Master Silver

Oracle Database を操作する上で、データの整合性を守るために最も重要な概念が「Oracle トランザクション」です。意図しないデータ変更を防いだり、複数の処理を一つのまとまりとして確定させたりするには、トランザクションの制御(COMMIT や ROLLBACK)を正しく理解する必要があります。

この記事では、開発者や DBA 初級者が知っておくべきトランザクションの開始・終了ルール、セーブポイント の活用法、および運用上の注意点を実例とともに解説します。

💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?

Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?

結論:トランザクション制御のポイント(やることリスト)

まずは、トランザクション操作の全体像を把握しましょう。

  • 開始: 特別なコマンドは不要。最初の DML(INSERT/UPDATE/DELETE)で自動開始される。
  • 確定: COMMIT で変更をデータベースに永続保存する。
  • 取消: ROLLBACK で変更を破棄し、開始前の状態に戻す。
  • 部分的取消: SAVEPOINT を置き、ROLLBACK TO でその時点まで戻す。
  • 注意: CREATETRUNCATE などの DDL は、実行時に自動でコミットされる(暗黙コミット)。

1. トランザクションの基本と仕組み

トランザクションとは?

トランザクションとは、**「分割できない一連の処理単位」**のことです。銀行の振込処理(A口座から出金し、B口座に入金する)が典型例で、片方だけ成功してもう片方が失敗すると困るため、「全て成功するか、全て失敗するか(All or Nothing)」を保証します。

ACID特性

データベースの信頼性を支える4つの特性です。

  • Atomicity(原子性): すべて実行されるか、全く実行されないか。
  • Consistency(一貫性): データの矛盾(整合性制約違反など)がない状態を保つ。
  • Isolation(独立性): 実行中のトランザクションは、他から干渉されない(分離レベルで制御)。
  • Durability(永続性): 一度コミットすれば、障害が起きてもデータは消えない。

他RDBMSとの違い(SQL Serverなど)

SQL Server などでは BEGIN TRANSACTION で明示的に開始することが多いですが、Oracle Database では DML を実行した瞬間に自動的にトランザクションが開始されます。この違いは重要です。


2. Oracle SQL トランザクションの実装手順

操作の流れをフローチャートで確認します。

[ アイドル状態 ]
      ↓
[ DML実行 (INSERT/UPDATE等) ]  ← ここでトランザクション自動開始
      ↓
      ├─→ [ SAVEPOINT 設定 ] (任意: 戻りポイントを作成)
      │        ↓
      │   [ DML実行 (追加の変更) ]
      │        ↓
      ├─→ [ ROLLBACK TO <SP> ] (任意: セーブポイントまで戻す)
      ↓
[ 終了判断 ]
      ├─→ COMMIT   (確定: 全変更を保存) ──┐
      └─→ ROLLBACK (破棄: 全変更を取消) ──┴→ [ トランザクション終了 ]

3. 実機で学ぶ実行例(セーブポイント活用)

実際に SQL*Plus や SQL Developer で実行できるコード例です。

ここでは、以下のシナリオを想定します。

  1. テスト用テーブルを作成。
  2. データを1件挿入(トランザクション開始)。
  3. セーブポイントを作成。
  4. データを誤って更新。
  5. セーブポイントまで戻して修正。
  6. 最後にコミットして確定。

💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?

Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?

事前準備と実行コード

[!WARNING]

SQL 内にはマルチバイト文字(日本語)を含めず、コメントでのみ補足しています。実環境で試す場合は、テスト用のスキーマを使用してください。

-- 1. Setup: Create a test table (DDL auto-commits)
CREATE TABLE trans_test (
    id NUMBER PRIMARY KEY,
    val VARCHAR2(20)
);

-- 2. Start Transaction implicitly by INSERT
INSERT INTO trans_test (id, val) VALUES (1, 'Initial Data');

-- Verify: Data is visible to this session, but not others yet.
SELECT * FROM trans_test;

-- 3. Set a Savepoint
SAVEPOINT sp_before_update;

-- 4. Execute an UPDATE (Assume this is a mistake or tentative change)
UPDATE trans_test SET val = 'Wrong Data' WHERE id = 1;

-- Verify the change
SELECT * FROM trans_test;
-- Result: id=1, val='Wrong Data'

-- 5. Partial Rollback: Go back to the Savepoint
ROLLBACK TO SAVEPOINT sp_before_update;

-- Verify: The UPDATE is undone, but INSERT is still alive
SELECT * FROM trans_test;
-- Result: id=1, val='Initial Data'

-- 6. Commit: Make the INSERT permanent
COMMIT;

実行結果:

SQL> -- 1. セットアップ: テストテーブルを作成する (DDL 自動コミット)
SQL> CREATE TABLE trans_test (
2 id NUMBER PRIMARY KEY,
3 val VARCHAR2(20)
4 );

Table created.

SQL> -- 2. INSERTによって暗黙的にトランザクションを開始する
SQL> INSERT INTO trans_test (id, val) VALUES (1, 'Initial Data');

1 row created.

SQL> -- 確認: データはこのセッションでは表示されますが、他のセッションではまだ表示されません。
SQL> SELECT * FROM trans_test;

ID VAL
---------- --------------------
1 Initial Data

SQL> -- 3. セーブポイントを設定
SQL> SAVEPOINT sp_before_update;

Savepoint created.

SQL> -- 4. UPDATE を実行します (これは間違いまたは暫定的な変更であると想定します)
SQL> UPDATE trans_test SET val = 'Wrong Data' WHERE id = 1;

1 row updated.

SQL> -- 変更を確認する
SQL> SELECT * FROM trans_test;

ID VAL
---------- --------------------
1 Wrong Data

SQL> -- 5. 部分ロールバック: セーブポイントに戻る
SQL> ROLLBACK TO SAVEPOINT sp_before_update;

Rollback complete.

SQL> -- 検証: UPDATE は取り消されましたが、INSERT はまだ有効です
SQL> SELECT * FROM trans_test;

ID VAL
---------- --------------------
1 Initial Data

SQL> -- 6. Commit: INSERTを永続化する
SQL> COMMIT;

Commit complete.

コードの解説

  • SAVEPOINT sp_before_update;:この時点の状態に名前(ラベル)を付けます。メモリ上にポインタが置かれるイメージです。
  • ROLLBACK TO SAVEPOINT …;:指定したラベル以降の操作のみを取り消します。ラベルより前の INSERT は維持されているため、ゼロからやり直す必要がありません。
  • COMMIT;:REDOログに書き込みを行い、データを確定させます。この時点で他のユーザーからもデータが見えるようになります。

4. トランザクション管理のトラブルシューティング

トランザクション操作でよく発生するエラーと対処法です。

エラーコードエラー内容原因と対処
ORA-00054リソース・ビジー、NOWAITが指定…原因: 対象行を別のトランザクションがロックしており、待機できない設定でアクセスした。
対処: ロック解放を待つか、運用ルールの確認。
ORA-02049分散トランザクションが待機…原因: DBリンク先などのロック待ちでタイムアウトした。
対処: ロック保持者の特定と解放。
ORA-30036UNDO表領域を拡張できません原因: トランザクションが巨大すぎて、変更履歴(UNDO)があふれた。
対処: 巨大な更新を分割してコミットする、またはUNDO表領域を拡張する。

5. 運用・監視・セキュリティ上の注意

自動コミット(Auto Commit)の罠

SQL*Plus や一部の GUI ツールには「自動コミット」機能があります。これが ON になっていると、UPDATE 直後に勝手に COMMIT され、取り返しがつかなくなります。

  • 確認方法(SQL*Plus): SHOW AUTOCOMMIT
  • 対策: 本番環境接続時は必ず OFF であることを確認する。

DDL の暗黙コミット

CREATE, ALTER, DROP, TRUNCATE などの DDL を実行すると、その直前に 暗黙的に COMMIT が発行されます。

「データを INSERT した後、TRUNCATE で別のテーブルを掃除した」場合、INSERT したデータも確定されてしまうため注意が必要です。

ロックの長期保持(ブロッキング)

COMMITROLLBACK もしないまま放置すると、その行(または表)に対するロックが保持され続けます。これにより、他のユーザーの処理が待たされ(ハングアップ状態)、システム障害に見えることがあります。

  • ベストプラクティス: トランザクションは可能な限り短くし、ユーザー対話(画面入力待ちなど)を含めないように設計します。

6. よくある質問 (FAQ)

Q1. 間違って COMMIT してしまいました。戻せますか?

A. 通常の ROLLBACK では戻せません。

ただし、Oracle のフラッシュバッククエリ機能を使えば、「15分前の状態」などを参照・復元できる可能性があります(UNDO データの保持期間に依存)。

  • 例: SELECT * FROM trans_test AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '15' MINUTE);

Q2. ネスト(入れ子)したトランザクションは作れますか?

A. Oracle Database は、標準ではネストしたトランザクション(トランザクションの中に別のトランザクションを開始する)をサポートしていません。

代わりに SAVEPOINT を使用するか、PL/SQL であれば PRAGMA AUTONOMOUS_TRANSACTION(自律型トランザクション)を使用して、メイン処理とは別の独立したコミットを行うことは可能です。

Q3. トランザクション分離レベルとは何ですか?

A. 他のトランザクションの影響をどれだけ受けるかの設定です。Oracle のデフォルトは READ COMMITTED(確定したデータのみ読み取る)です。厳密な整合性が必要な場合は SERIALIZABLE を使いますが、同時実行性が下がるため注意が必要です。


まとめ

Oracle トランザクションを適切に扱うことは、データベースエンジニアの基本スキルです。

  1. 開始は自動:DML を投げた瞬間に始まる。
  2. 終了は必須:処理が終わったら必ず COMMITROLLBACK を行う。
  3. 部分修正:長い処理には SAVEPOINT を挟むとリカバリが楽になる。
  4. DDLに注意:DDL は実行前に強制コミットを伴う。

まずは開発環境で、わざとエラーを起こしたりセーブポイントを使ったりして、挙動を体感してみてください。

本記事は Oracle Database 19c を対象に解説します(他バージョンは画面や既定値が異なる場合があります)。


[参考]
Oracle Database SQL言語リファレンス 19c

💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?

Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?

コメント

タイトルとURLをコピーしました