Oracle UNDO の内部構造を徹底解説:UNDO Tablespace、CR Clone、ORA-01555 まで

はじめに

この記事では、Oracle DatabaseのUNDOの内部実装を深掘りします。

InnoDB、PostgreSQLに続く3本目です。Oracleは最も早くMVCCを実装したDBの1つで、UNDO管理の成熟度が高いです。Oracle 19c / 23aiを中心に解説します。

OracleのMVCCアーキテクチャ

OracleはInnoDBと同じく「最新版をテーブルに、旧版をUNDO領域に」保持する方式です。

Oracle用語              InnoDB用語           PostgreSQL用語
──────────────────────────────────────────────────────────
UNDO Segment           Rollback Segment     ―(Heap内に保持)
UNDO Tablespace        Undo Tablespace      ―
CR Clone               バージョンチェーン     xmin/xmax
SCN                    Transaction ID       Transaction ID
ORA-01555              ―                    ―

UNDO Segmentの構造

UNDO Tablespace

OracleのUNDOデータは専用のUNDO Tablespaceに格納されます。

SHOW PARAMETER undo;

NAME                  VALUE
--------------------  ---------------
undo_management       AUTO
undo_retention        900            -- 秒(デフォルト15分)
undo_tablespace       UNDOTBS1

UNDO Segment

UNDO Tablespace内に複数のUNDO Segmentがあります。各トランザクションは1つのUNDO Segmentに割り当てられます。

SELECT segment_name, status, tablespace_name
FROM dba_rollback_segs WHERE tablespace_name = 'UNDOTBS1';

SEGMENT_NAME    STATUS    TABLESPACE_NAME
--------------  --------  ---------------
_SYSSMU1$       ONLINE    UNDOTBS1
_SYSSMU2$       ONLINE    UNDOTBS1
...

UNDO Segment内はエクステント(連続ブロック群)で構成され、循環的に再利用されます。InnoDBのRollback Segmentと同じ概念です。

CR Clone(Consistent Read)

Oracleの読み取り一貫性の核心がCR Clone(Consistent Read Clone)です。

仕組み

読み取りトランザクションがデータブロックにアクセスしたとき、そのブロックに自分のSCN以降の変更が含まれていたら:

1. データブロックのコピーをメモリ上に作成(CR Clone)
2. UNDO Segmentから旧値を取得
3. CR Cloneに旧値を適用(ロールバック)
4. 必要なだけ繰り返して、自分のSCN時点の状態を復元
5. CR Cloneから読み取る
Buffer Cache:
  Current Block: [id=1, salary=5000, SCN=200]  ← 最新版

  読み取りTx(SCN=150で開始)がアクセス:
    → SCN 200 > 150 なので、CR Cloneを作成
    → UNDO Segmentから SCN=200 の変更前値を取得
    → CR Clone: [id=1, salary=3000, SCN=100]  ← SCN=150時点の状態

InnoDBとの比較

InnoDB Oracle
旧版の取得 UNDO LogのRoll Ptrを辿る CR Cloneを作成しUNDOを適用
旧版の場所 UNDO Log内のレコード Buffer Cache上のCR Clone
コスト チェーンが長いと遅い ブロック全体のコピー+ロールバック

ORA-01555:Snapshot Too Old

PostgreSQLにはテーブル肥大化の問題がありました。OracleにはUNDO領域の上書きによるORA-01555があります。

発生メカニズム

1. 長時間の読み取りクエリが開始(SCN=100)
2. 他のトランザクションがデータを更新し続ける
3. UNDO Segmentが循環利用され、SCN=100時点のUNDOデータが上書きされる
4. 読み取りクエリがCR Cloneを作ろうとするが、必要なUNDOがもうない
5. ORA-01555: snapshot too old

対策

-- UNDO保持時間を延長(デフォルト900秒)
ALTER SYSTEM SET undo_retention = 3600;  -- 1時間

-- UNDO Tablespaceを十分に大きくする
ALTER TABLESPACE UNDOTBS1 ADD DATAFILE '/u01/oradata/undotbs02.dbf' SIZE 10G;

-- Guaranteed Undo Retention(UNDOの上書きを禁止)
ALTER TABLESPACE UNDOTBS1 RETENTION GUARANTEE;
InnoDB PostgreSQL Oracle
UNDO不足の症状 History List肥大化 テーブル肥大化 ORA-01555
原因 長時間Tx/ReadView VACUUMの遅延 UNDO上書き
対策 Purge高速化 autovacuumチューニング undo_retention延長

Automatic Undo Management

Oracle 9i以前は手動でRollback Segmentを管理する必要がありました。9i以降はAUM(Automatic Undo Management)がデフォルトです。

AUMでは: – UNDO Segmentの数とサイズを自動調整 – トランザクションへのUNDO Segment割り当てを自動化 – undo_retentionに基づいてUNDOの保持期間を管理

InnoDBも同様に自動管理です。PostgreSQLはそもそもUNDO領域が不要(Heap内にバージョンを保持)なので、この問題自体がありません。

まとめ

トピック InnoDB PostgreSQL Oracle
バージョン保管 UNDO Log Heap内 UNDO Segment
読み取り一貫性 ReadView + Roll Ptr Snapshot + xmin/xmax CR Clone
UPDATEの動作 in-place更新 新タプル挿入 in-place更新
UNDO不足時 History List肥大化 テーブル肥大化 ORA-01555
旧版の削除 Purge VACUUM UNDO Segmentの循環再利用
管理 自動 autovacuum AUM(自動)

次回はSQL Server Versioningを解説します。

参考文献

コメントする