Oracle DatabaseのUNDO(アンドゥ)は、トランザクションの整合性と同時実行制御を支える非常に重要な仕組みです。
UNDOを正しく理解しておくことは、エラー回避やパフォーマンス維持、障害対応の観点からもDBAにとって必須の知識です。
この記事では、UNDOの役割と仕組みだけでなく、実際にemp表を使ってUNDOの使用量を確認する手順まで、実行可能なSQL付きで丁寧に解説します。
💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?
Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?
UNDOとは?
UNDOとは、トランザクションでデータを変更する際に、その「変更前の情報」を記録しておくための仕組みです。
これにより、以下のことが可能になります:
- トランザクションの取り消し(ROLLBACK)
- 読み取り一貫性(Read Consistency)の保証
- フラッシュバック問合せの実現(過去の状態に戻す)
UNDOとREDOの違い
| 比較項目 | UNDO | REDO |
|---|---|---|
| 保持内容 | 変更前のデータ | 変更操作の再実行に必要な情報 |
| 主な用途 | ROLLBACK、読み取り一貫性、FLASHBACK | リカバリ、障害時のロールフォワード |
| 格納場所 | UNDOセグメント(UNDO表領域) | REDOログファイル |
図で理解:UNDOの利用シーン
トランザクションA:
UPDATE emp SET sal = 5000 WHERE empno = 7900;
トランザクションB:
SELECT * FROM emp;
→ Bのクエリは、AのCOMMIT前でも
UNDOを使って「変更前の値」を取得!
UNDOが必要な理由
- 他ユーザーがトランザクション中のデータを読んでも整合性が崩れない
- 万一、ROLLBACKや障害復旧が発生しても、元の状態に戻せる
Oracleは、「誰がいつ何を見ても矛盾のない状態」を保証するためにUNDOを用いています。
UNDOの実体:UNDOセグメントとUNDO表領域
- UNDO情報は「UNDOセグメント」という単位で格納されます
- UNDOセグメントは、UNDO専用の表領域(UNDO表領域)に保存されます
Oracle 9i以降は「自動UNDO管理(AUM)」が標準で、UNDO表領域はOracleが自動的に管理します。
UNDOの確認手順:emp表を使った実践例
ここからは実際に、OracleでUNDOがどのように発生し、確認できるかを検証します。
Step 1:emp表の作成
CREATE TABLE emp (
empno NUMBER(4) PRIMARY KEY,
ename VARCHAR2(10),
job VARCHAR2(9),
mgr NUMBER(4),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2)
);
Step 2:初期データの挿入(SCOTTスキーマ風)
INSERT INTO emp VALUES (7369, 'SMITH', 'CLERK', 7902, TO_DATE('1980-12-17','YYYY-MM-DD'), 800, NULL, 20);
INSERT INTO emp VALUES (7900, 'JAMES', 'CLERK', 7698, TO_DATE('1981-12-03','YYYY-MM-DD'), 950, NULL, 30);
COMMIT;
Step 3:トランザクションを発生させる(COMMITしない)
-- UNDOを発生させる(COMMITしない)
UPDATE emp SET sal = sal + 500 WHERE deptno = 20;
この状態で、Oracleは UNDOセグメント に「変更前の給与」を記録しています。
Step 4:UNDO使用量の確認
SELECT t.used_ublk * TO_NUMBER(p.value) / 1024 / 1024 AS undo_used_mb
FROM v$transaction t,
v$parameter p
WHERE p.name = 'db_block_size';
🔍 used_ublk は、現在のトランザクションで使用されているUNDOブロック数を示します。
🔍 db_block_size(通常は8192バイト)との積により、使用量をMB単位で算出します。
Step 5:セッションごとに確認したい場合(任意)
SELECT s.sid,
s.serial#,
t.used_ublk * TO_NUMBER(p.value) / 1024 / 1024 AS undo_used_mb
FROM v$transaction t
JOIN v$session s ON t.ses_addr = s.saddr
JOIN v$parameter p ON p.name = 'db_block_size';
よくあるトラブル:ORA-01555の原因はUNDOにある?
ORA-01555: スナップショットが古すぎます
これは、長時間かかるSELECT文の間に必要なUNDO情報が上書きされた場合に発生します。
対策
UNDO_RETENTIONを適切に延長(例:1800秒)- UNDO表領域に十分な空き容量を確保
SHOW PARAMETER undo_retention
図:ROLLBACKとUNDOの関係
┌────────────┐
│ UNDO情報 │ ← 更新前の状態
└────────────┘
↓
[ROLLBACK発行]
↓
┌────────────┐
│ 実表データ復元 │ ← UNDOを使って元に戻す
└────────────┘
UNDOのベストプラクティスまとめ
| 項目 | 解説 |
|---|---|
UNDO_RETENTION の調整 | 長時間トランザクションやフラッシュバックに耐えられるように設定 |
| 表領域サイズを確保 | 自動拡張を有効にするか、予備容量を十分に設定する |
| 自動UNDO管理を使用 | Oracle推奨。手動UNDO管理は非推奨 |
| 定期的な監視 | v$undostat や DBA_UNDO_EXTENTS でUNDOの使用傾向を把握する |
まとめ
| 項目 | 内容 |
|---|---|
| UNDOとは | 変更前の状態を保持する情報で、トランザクション制御に不可欠 |
| 主な用途 | ROLLBACK、一貫性確保、フラッシュバック |
| REDOとの違い | UNDOは「戻す」、REDOは「再現する」 |
| 使用量確認方法 | v$transaction × db_block_size を用いて現在のUNDO使用量を取得 |
| 実践手順 | emp表を使ってトランザクションを発生させ、UNDOを確認可能 |




コメント