5月に入り、令和時代も、丸2年が経ちました。
時代の半分以上がコロナ禍というのがあれですが。。。
さて、今日のテーマは、
Oracle DabataseのUNDO(アンドゥー)管理について。(確認したOracleのバージョンは19cです)
もくじ
1.UNDOとは
3.UNDO表領域
該当するOracleのドキュメントはこちら。
1.UNDOとは
◎UNDOの主な役割
まずはOracle Dabataseのドキュメントを引用。
Oracle Databaseでは、データベースの変更をロールバックまたは取り消すために使用する情報を作成して管理します。これらの情報は、主にコミットされる前のトランザクションの処理レコードから構成されます。これらのレコードを総称してUNDOと呼びます。
UNDOレコードは次の処理に使用されます。
ROLLBACK文を発行したときのトランザクションのロールバックデータベースのリカバリ
読取り一貫性の実現
Oracle Flashback Queryを使用した過去のある時点のデータの分析
Oracle Flashback機能を使用した論理的な破損のリカバリ
データベース処理では、何かあった時に、ロールバックをすることがある。
ロールバックは、主に、コミットされず中途半端な状態で終わってしまったデータ更新を元に戻す作業となる。
ということは、中途半端なところまでのデータ更新についても、どこまで処理ができたのか知っておかないと、
何を元に戻せばいいのかわからなくなってしまう。
ドキュメントにある「主にコミットされる前のトランザクション」とは、そういった、中途半端な部分の情報のことであり、
それら中途半端な情報への処理レコードに対して、UNDOという名称がついているのである。
ドキュメントにある、UNDOレコードが使用される各処理の詳細は、以下の通りである。
◎ROLLBACK文を発行したときのトランザクションのロールバック
UNDO本来の目的そのままの処理だが、
何らかの理由で、コミット前の状態に戻す(ロールバック)ときに、コミット前・処理途中の内容を確認するために利用される。
コミット前・処理途中の内容がわかれば、その内容をなかったことにすれば良いとわかるので、
正しい対象へのロールバックが可能になる。
◎データベースのリカバリ
障害発生時等で、REDOログファイルからリカバリを行う際、
「REDOログに残っている処理操作のうち、データファイルにコミットされていない処理」が存在する。
しかし、REDOログによりリカバリをすると、コミットされていない、中途半端な状態のものまでも、
REDOログに処理が残っていればデータファイルに適用されてしまうことになる。
中途半端な状態の処理をコミットしてしまうと、トランザクションのACID特性が守られず、データが正常な状態でなくなってしまう。
そのため、中途半端な状態の処理はすべて無かったことにする必要がある。
中途半端な状態の処理(=無かったことにすべき処理)が何であるかを判断し、削除するために、UNDOレコードが活躍する。
利用場面は違えど、本質的には1つ目のロールバックと同じことをしているといえる。
◎読み取り一貫性
データが大量にあるために、取得に時間のかかる処理があったとする。
データを取得する最中に、取得の最中に別のトランザクションが発生し、最初のほうに取得したデータが更新される可能性もある。
すると、最初のほうに取得したデータと、最後のほうに取得したデータで、データの整合性が保てなくなってしまう。

こうした事態を防ぐために、UNDOでは、データを取得し始めた時点からのデータを保持しておくこともできるようになっている。
UNDOによって、最初と最後で取得する(読み取る)データの一貫性を保つことができる。
◎Oracle Flashbackの利用
Flashbackは、過去のある時点(例:1日前など)の状態に、データベースを戻すことができる機能。
スナップショットに近いが、あらかじめスナップショットを取っておく必要はない。
その代わり、過去のある時点の状態を確認するために、UNDOレコードが使われる。
従って、UNDOレコードが残っている時点以降の状態にまでしか戻せない。
(1日前までのUNDOレコードしかない場合、3日前には戻せない)
データベースのリカバリ方法の1つだが、
・高速リカバリ領域をデータベースに設定しておく必要がある
・ARCHIVELOGモードでデータベースが実行されている必要がある
などの制約がある。
また後述の通り、UNDOレコードの保存期間は動的に管理されるため、
場合によってはUNDOレコードが残っておらず、戻したいと思った時点に戻せないこともある。
さらに、過去のある時点の状態に戻すため、
その時点~今までのデータ更新はなかったことになってしまう。
本番環境ではけっこう使いにくそうな機能である。(開発・テスト環境では便利かもしれない)
2.UNDOの管理方法
UNDO、つまり、ロールバック情報と、UNDOデータの領域を管理するために、「自動UNDO管理」という機能がある。
名前の通り、Oracleによって自動的に管理をしてくれるしくみであり、
UNDOの管理は「UNDO表領域」において行われる。
自動管理の対極として、UNDO表領域は使用せず、手動で自らUNDOを管理する方法(ロールバック・セグメント管理と呼ばれる)もある。
しかし、手動での管理はかなり煩雑となるため、自動管理が強く推奨されている。
DBを生成したときのデフォルトの管理方法も、自動UNDO管理となっている。
ということで、以降は、自動UNDO管理を行うものとして記述する。
3.UNDO表領域
自動UNDO管理において、UNDOレコードは、UNDO専用の表領域(UNDO表領域)に保持される。
(専用の表領域がない場合、SYSTEM表領域という、Oracleのシステム管理用表領域(作成必須)の中に、UNDO領域が確保される。が、UNDO専用の表領域を別途作成することが推奨されており、専用表領域がないとアラートが出力される)
データベースの生成時や、既存DBに対して任意のタイミングでUNDO表領域を新規作成することができるが、
アクティブにできるUNDO表領域は1つだけである。
(複数UNDO表領域がある場合、条件をクリアすれば、アクティブにするUNDO表領域の切り替えは可能)
4.UNDOレコードの保存期間
UNDO表領域には、コミット前のデータ等がどんどん新しく蓄積されていくことになる。
UNDOレコードの取得の本来の目的は、コミット前のトランザクションのデータを保持することで、適切なロールバックやリカバリを行うことにある。
そのため、トランザクションがコミットされれば、関係するUNDOレコードは不要となるようにも思うが、
読み取り一貫性や、Oracle Flashbackの正常終了のために、古い情報も可能な限り長い間保存することが推奨される。
特にOracle Flashbackにおいては、長期間保存すべき要件となることもあるため、注意が必要である。
保存期間を超えた場合、古いUNDO情報は新しいUNDO情報によって上書きされ、消える。
保存期間は、自動UNDO管理において、Oracleによって動的に管理・調整される。
ただし調整方法は、UNDO表領域のサイズ上限決定方法により、以下の表のように2通りある。
UNDO表領域のサイズ上限の決定は、UNDO表領域生成時のサイズ調整パラメータ「AUTOEXTEND」の設定による。
| AUTOEXTEND (自動拡張) |
サイズの上限 | 保存期間の調整 | 注意点 |
|---|---|---|---|
| OFF | あらかじめ指定した固定サイズ | 領域のサイズと現行のシステムの負荷を踏まえ、 最適な保存期間が動的に調整される。 |
十分なサイズの固定値を指定しないと、 領域不足で読み取り一貫性を保てなくなったり、 新しいトランザクションのUNDOレコード格納先がなくDMLが失敗したりする。 |
| ON | 指定サイズと保存期間に基づき、 必要に応じて表領域サイズが自動で拡張される。 |
システムでアクティブな最長実行問合せより 若干長くなるように動的に調整される。 |
自動拡張により、UNDO領域の肥大化が起きていないか監視する必要がある。 また、Oracle Flashback使用時は保存期間が十分でないことがある。 |
なお、AUTOEXTEND=ONとした場合、保存期間の最低秒数を指定しておくことが可能である。(OFFの場合は指定しても無視される)
最低秒数は、初期化パラメータ「UNDO_RETENTION」によって設定する。
設定すると、設定値よりも長い秒数期間保存されるが、
もしUNDO領域サイズが不足していた場合、表領域サイズが自動拡張されるしくみになっている。
さいごに。
どうでもいいですが、友達に、あんどぅーと呼ばれている人がいて(名字が安藤)、
UNDOと聞くたびにその人のことが思い出されます(`・ω・)
今回は以上!

