ロールバック・セグメントを調整する
![]() |
図5●ロールバッック・セグメントの仕組み |
次は,ロールバック・セグメント*に関するエラーだ。「ORA-01555 スナップショットが古すぎます」というエラー・コードは有名なため,ある程度Oracleで運用や開発を経験された方であれば,遭遇したことがあるのではないだろうか。
トラブルの現象としては,参照系プログラムのエラーが報告されたり,処理が無応答になったりする。この状況で,例によってアラート・ファイルを調べてみる。無応答になった時間の前後を見ると,「ORA-01555 スナップショットが古すぎます(ロールバック・セグメント番号: 1,名前:rollbacksegment_name が小さすぎます)」とある。
その意味をご存知の方も多いと思うが,改めてロールバック・セグメントの役割からおさらいしておこう。第1回でも触れたが,ロールバック・セグメントは,データの変更前のイメージを保持し,トランザクションのロールバック,回復,読み取り一貫性の保証のために使用されるデータベース・オブジェクトである(図5[拡大表示])。
ORA-01555は,ロールバック・セグメントが上書きされ,読み取り一貫性が保てないために出るエラーである。このエラーが発生する原因は以下の4つが代表的なものである。それぞれ解決のポイントが異なるため,覚えておきたい。
(1)用意したロールバック・セグメントの数と大きさに対して,データベースへの変更が多過ぎる場合。データベースを更新するトランザクションが多く,頻繁にコミット*が発せられると,ロールバック・セグメント上のブロックが再利用される確率が高くなる。このようなシステムに対して読み取り量の多い検索を行うと,変更前のイメージが取得できない可能性が高くなる。この場合,ロールバック・セグメントの数を増やす,各々の容量を増やすことで対処する。
(2)ロールバック・セグメントが破壊されている場合。必要な更新前イメージが含まれているロールバック・セグメントが破壊されているため,イメージを取得できずに該当のエラーとなる。この場合,ロールバック・セグメントの回復処理を行ってからトランザクションを再試行する。
(3)コミット前からの検索カーソルをオープンし,同じ表に対してフェッチ→更新→コミットを繰り返した場合。ロールバック・セグメントは循環して使用されるが,余りに回転が速いと必要な更新前イメージが取得できなくなる。このケースでは,コミットの回数を減らして必要なイメージがロールバック・セグメント上にとどまる確率を高めることでエラーの発生頻度を下げられる。
(4)OPTIMALの値が小さい場合。後述するが,ロールバック・セグメントを作成する際は,その大きさを最適化するためにOPTIMALというパラメータを指定する。ORA-01555の発生を防ぐために,Oracleはコミットされた情報をできるだけ長時間ロールバック・セグメント上に保持しようとする。しかしOPTIMALを小さくするとエクステントが解放されやすくなり,コミットされた情報が失われやすくなる。トランザクションの実行時間に対してOPTIMALの値が小さい場合には当該エラーが発生しやすいので調整が必要だ。
ロールバック・セグメントを見積もる
さて,このようなロールバック・セグメントのエラーを回避するためには,ロールバック・セグメントの適正な大きさなどを見極めなければならない。ただし,理論値だけで正確に見積もることは難しい。テスト段階などで実測し,見積もりに役立てることが大切だ。ロールバック・セグメントの必要領域は,以下のガイドラインとUNDO*の量を推定することにより,拡張/縮小の少ない領域サイズが見積もれる。
(1)ロールバック・セグメント用表領域を作成
ロールバック・セグメントの表領域は,ユーザー表領域とは別に作成する。テスト中は表領域の追加を行うのが面倒なので,最初に十分な大きさの表領域を作成する。
(2)ロールバック・セグメントを作成
ロールバック・セグメントが最大でも10~30エクステントになるように作成する。また,各ロールバック・セグメントのエクステント・サイズはすべて同じにする。
(3)ロールバック・セグメントをONLINEにする*5
(4)本番並みのトランザクションを実行
本番業務と同等の負荷をかけ,より現実的なロールバック・セグメントのサイズを推定する。
(5)トランザクションの競合を確認する
以下のSQL文によってインスタンス開始以降の待ちの回数を求めることができる。競合がある場合はロールバック・セグメントの数を増やす。
SELECT * FROM V$WAITSTAT WHERE CLASS = 'undo header';
(6)ロールバック・セグメントの最大を見極める
この最大サイズをMinimum Coverage Sizeと呼ぶ。これがロールバック・セグメントの理想的な大きさである。
(7)エクステントの数をチェックする
最大サイズが10エクステント以下に収まる場合は,各エクステントのサイズを縮める。逆に,30エクステントを超える場合は,各エクステントのサイズを拡張する。
拡張したロールバック・セグメントを縮小する
ロールバック・セグメント運用する際は以下のポイントにも注意が必要だ。更新系トランザクションは1個のロールバック・セグメントを確保し,あるトランザクションのロールバック情報は,別のロールバック・セグメントにはまたがらない。例えば,更新量の少ないトランザクションでは,ロールバック・セグメントのエクステントを全部使い切る前にトランザクションは終了するので,別のトランザクションが以前のトランザクションの領域を再利用できる。
しかし,一度に大量の更新を行うトランザクションの場合,そのトランザクションによって,あるロールバック・セグメントのエクステントを全部使い切ってしまうケースが発生する。その時には,該当のロールバック・セグメントは拡張され,更に書き込みが続けられる。
拡張されたロールバック・セグメントは,以下の方法を採らない限り縮小しない。
(1)ロールバック・セグメント作成時にOPTIMALを指定して,指定サイズまで自動縮小させる
CREATE ROLLBACK SEGMENT rbnai TABLESPACE rbs STORAGE (INITIAL 20K NEXT 20K MINEXTENTS 5 MAXEXTENTS unlimited OPTIMAL 100K);
(2)手動で縮小する
ALTER ROLLBACK SEGMENT rb1 SHRINK TO 50K;