Oracleをいじっていると聞くことがあるUNDOという言葉、なんとなくロールバックのデータを保持しているのかと思っていたけどどうやらそれだけではないらしいので少し深堀して調べてみた。
UNDOデータとは何か
簡単に言うと、トランザクション中変更したデータの元データの事をいう。
deleteやupdate文を流した後に、流す前のデータを保持している簡単に言うと期間限定のバクアップのこと。
つまり、このデータがあればいつでも、テーブルを更新前の状況にできるということだ。
UNDOデータの使い道
トランザクションのロールバック
おそらく最も認知されているUNDOデータの利用方法
コミットしていないトランザクションをロールバックするのに利用する。
読み取り一貫性の確保
テーブルを更新しても、コミットしない限りほかのユーザーやセッションには表示されない
フラッシュバック機能
テーブルを昔のある時点まで、戻す機能で利用される。
これはのちに述べるUNDOデータの保存期間との兼ね合いもあるがとても便利な機能。
DBリカバリ
DBに何か障害があった場合、トランザクションを張る前の状態に戻すのに利用する。
UNDOセグメントとUNDO表領域
UNDOデータはUNDOセグメントに格納されます。UNDOデータは必ず一つのセグメントに格納されてほかのセグメントにまたがることはありません。1つのトランザクションにつき1つのUNDOデータを作成するで参照するセグメントも1つになるということ。
逆にUNDOセグメント内に複数のUNDOデータが格納されることはある。
このUNDOセグメントはUNDO表領域内に格納される。
1つのインスタンスにつきUNDO表領域は1つ必要になる。
UNDOの保存期間
最小保存期間
UNDOはトランザクションをコミットすると古いUNDOデータが不要になることがあります。また、フラッシュバック機能を実行するために古いUNDOデータが必要になる。古いUNDOデータをトランザクションが終了した後も残しておくには、UNDO_RETENTIONを設定する。
UNDO_RETENTIONパラメーターの値絵を変更すると最小保存期間を変更できる。
デフォルト値では「900」が設定されている
保存期間の保証
保存期間の保証を有効にすることでUNDOデータの最小保存期間が保証される
保存期間を有効にするにはUNDO表領域を作成する際にRETENTION GUARANTEE句を指定する。
またALTER TABLESPACE文で指定を変更することもできる。
無効化するにはRETENTION NOGUARANTEE句を指定する
UNDO_RETENTIONの確認
公式リファレンスによると
現行のUNDO表領域に対してUNDOがOracle Databaseで保存される時間は、V$UNDOSTAT動的パフォーマンス・ビューのTUNED_UNDORETENTION列に問い合せて取得できる。
UNDOに関するエラー
UNDO表領域が小さくてエラーになる場合
UNDO表領域は自動拡張が可能である。この自動拡張機能がOFFになっており、UNDO表領域が小さい場合大量のデータ更新処理がおこなわれると、ORA-30036: UNDO表領域内でセグメントを拡張できません というエラーが出る。
読み取り一貫性が維持できない事による「スナップショットが古すぎます」
ORACLEは更新前にテーブルを確認した場合、更新する前のテーブルを確認し続ける。この時確認しているテーブルはUNDO領域に保存されたものである。
UNDO領域が狭い場合、UNDOの保存期間が短すぎる場合は、ORA-01555 スナップショットが古すぎます というエラーが出る。
参考
Oracle® Database管理者ガイド
社内SE雑記ブログ
Oracleデータベース・リファレンス
なんとなくを腑に落とすシリーズ ~第1回 UNDO(前編)
ORA-30036: UNDO表領域内でセグメントを拡張できません 株式会社コソール
OracleのUNDO表領域でやらかしてしまった話
Oracle Database ORA-01555 の原因と対処方法