Oracle Database を操作する上で、データの整合性を守るために最も重要な概念が「Oracle トランザクション」です。意図しないデータ変更を防いだり、複数の処理を一つのまとまりとして確定させたりするには、トランザクションの制御(COMMIT や ROLLBACK)を正しく理解する必要があります。
この記事では、開発者や DBA 初級者が知っておくべきトランザクションの開始・終了ルール、セーブポイント の活用法、および運用上の注意点を実例とともに解説します。
💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?
Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?
結論:トランザクション制御のポイント(やることリスト)
まずは、トランザクション操作の全体像を把握しましょう。
- 開始: 特別なコマンドは不要。最初の DML(INSERT/UPDATE/DELETE)で自動開始される。
- 確定:
COMMITで変更をデータベースに永続保存する。 - 取消:
ROLLBACKで変更を破棄し、開始前の状態に戻す。 - 部分的取消:
SAVEPOINTを置き、ROLLBACK TOでその時点まで戻す。 - 注意:
CREATEやTRUNCATEなどの 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件挿入(トランザクション開始)。
- セーブポイントを作成。
- データを誤って更新。
- セーブポイントまで戻して修正。
- 最後にコミットして確定。
💰 【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-30036 | UNDO表領域を拡張できません | 原因: トランザクションが巨大すぎて、変更履歴(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 したデータも確定されてしまうため注意が必要です。
ロックの長期保持(ブロッキング)
COMMIT も ROLLBACK もしないまま放置すると、その行(または表)に対するロックが保持され続けます。これにより、他のユーザーの処理が待たされ(ハングアップ状態)、システム障害に見えることがあります。
- ベストプラクティス: トランザクションは可能な限り短くし、ユーザー対話(画面入力待ちなど)を含めないように設計します。
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 トランザクションを適切に扱うことは、データベースエンジニアの基本スキルです。
- 開始は自動:DML を投げた瞬間に始まる。
- 終了は必須:処理が終わったら必ず
COMMITかROLLBACKを行う。 - 部分修正:長い処理には
SAVEPOINTを挟むとリカバリが楽になる。 - DDLに注意:DDL は実行前に強制コミットを伴う。
まずは開発環境で、わざとエラーを起こしたりセーブポイントを使ったりして、挙動を体感してみてください。
本記事は Oracle Database 19c を対象に解説します(他バージョンは画面や既定値が異なる場合があります)。
[参考]
Oracle Database SQL言語リファレンス 19c
💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?
Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?




コメント