[RDS Oracle]REDOログファイルのサイズ変更方法

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは、yokatsukiです。

今回もAmazon RDS for Oracle(以下RDS Oracle)の話です。例によって、お客様からの相談から始まります…

アラートログファイルに気になるメッセージが…

運用中のRDS Oracleに関する相談を受けました。

「アラートログに以下のメッセージが毎日大量に出力されているのですが、これは普通なのでしょうか?」

Thread 1 cannot allocate new log, sequence 17097
Checkpoint not complete
  Current log# 4 seq# 17096 mem# 0: /rdsdbdata/db/XXSYSTEM_A/onlinelog/o1_mf_4_ckjwwbfz_.log
Thread 1 advanced to log sequence 17097 (LGWR switch)

うん、「普通ではない」ですね。かと言って緊急事態という訳でもありません。

これは、データベースに対して大量にトランザクション処理を発生させた場合、ログ情報が大量に発生したことでREDOログファイルのスイッチが頻発してしまい、チェックポイント処理が間に合わなくなっていることを示しています。
詳しくは以下のリンク先の説明図がわかりやすいと思います。チェックポイントの説明もありますので参考にしてください。

チェックポイント処理が終わればログ・スイッチは行われるので、データベース破損や停止の心配はありません。しかしこれが常時起きるのは、性能の面で良い状態ではありません。以下に記述する対処を行っておく必要があります。

一般的な対処法

チェックポイント処理の遅延に対する一般的な対処方法は、上記@ITの記事にもある通り、REDOログファイルのサイズを大きくして、ログ・スイッチのタイミングの間隔を長くすることです。下記マニュアルによるとログスイッチ間隔は20分に1回、ピーク時は15分に1回をベストとしているようです。

REDOログファイルの最適サイズを求める方法は、今回のエントリ趣旨と外れてくるため省略しますが、例えば試しにREDOログファイルサイズを500MBにする場合、以下の手順で作業を行います。

  • REDOロググループに、新しいサイズでREDOログファイルを追加する
    (異なるグループ番号で最低2つ追加)
ALTER DATABASE ADD LOGFILE GROUP <新規グループ番号> SIZE 500M;
  • REDOログの書き込み先を、新しいファイルにスイッチする
    (現在書き込み中のグループによって何度か繰り返す)
ALTER SYSTEM SWITCH LOGFILE;
  • 古いREDOログファイルをデータベースの登録から除去する
    (その後必要に応じてOSコマンドでファイル削除)
ALTER DATABASE DROP LOGFILE GROUP <既存のグループ番号>;

RDS Oracleの場合は?

さて、Amazon RDSですが、よく知られた事実として「ファイル操作ができない」ことが挙げられます。その為、RDS Oracleにおいても、ファイル操作を行うALTER SYSTEMやALTER DATABASE系のSQL文が、Masterユーザレベルでも禁止されています。

ということは、上記のALTER DATABASE ADD LOGFILEやALTER SYSTEM SWITCH LOGFILEが使えない、ということになります。

念の為SQL Developerから実施してみました。

次のコマンドの開始中にエラーが発生しました : 行 1 -
ALTER DATABASE ADD LOGFILE GROUP 4 SIZE 500M
エラー・レポート -
SQLエラー: ORA-01031: 権限が不足しています。
01031. 00000 -  "insufficient privileges"
*Cause:    An attempt was made to perform a database operation without
           the necessary privileges.
*Action:   Ask your database administrator or designated security
           administrator to grant you the necessary privileges

ダメですね…さあ困った。

しかしここで諦めずにAWSのドキュメントを探します。そうすると、以下の記述が見つかります。

REDOログファイルの追加と削除は、以下のPL/SQLパッケージプロシージャで実行できるとのことです。

exec rdsadmin.rdsadmin_util.add_logfile(size bytes);
exec rdsadmin.rdsadmin_util.drop_logfile(group#);

(やや余談ですが、AWSのマニュアルにおいては、「REDOログ」を「再実行ログ」と表現しています。確かにREDOの語源は「バックアップから障害発生までに発生したトランザクションを"再実行する"」ところからきているので、この訳になった気持はわかりますけどね…。)

さて、それからログのスイッチですが、これも記述がありました。

REDOログファイルのスイッチは、以下のPL/SQLパッケージプロシージャで実行できるとのことです。

exec rdsadmin.rdsadmin_util.switch_logfile;

これならいけそうですね。試してみます。

検証

使用環境

  • RDS for Oracle SE One
    • DBエンジンバージョン:12.1.0.1.v4
    • インスタンスサイズ:db.m3.large
    • データベース名:ORCL1
  • Oracle SQL Developer
    • バージョン:4.1.3.20

設定確認

インスタンス作成直後のREDOログファイルについては、Amazon Relational Database Service ユーザーガイドに以下の記述があります。

Oracle データベースエンジンを使用して新しく作成されたAmazon RDS インスタンスには、128 MB のオンライン再実行ログが
4 つあります。

以下のSELECT文で、REDOログファイルの設定を確認しました。

SELECT
  group#, member, (bytes/1024/1024) as mbytes, (v$log.status) as status
FROM
  v$log
JOIN
  v$logfile
USING
  (group#)
ORDER BY
  group#;

問い合わせ結果:

GROUP# MEMBER                                                MBYTES STATUS
------ ----------------------------------------------------- ------ -------
     1 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_1_cnjfc3ql_.log    128 CURRENT
     2 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_2_cnjfc529_.log    128 ACTIVE
     3 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_3_cnjfc6ly_.log    128 ACTIVE
     4 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cnjfc86f_.log    128 ACTIVE

確かに128MBのREDOログファイルが4つ設定されています。

REDOログファイル追加

上記ドキュメントに書かれていたPL/SQLパッケージを使用して、REDOログファイルのサイズを500MBに変更します。

exec rdsadmin.rdsadmin_util.add_logfile('500M');
PL/SQLプロシージャが正常に完了しました。

実行後、上記REDOログの設定を確認するSQLを実行してみます。

GROUP# MEMBER                                                MBYTES STATUS
------ ----------------------------------------------------- ------ -------
     1 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_1_cnjfc3ql_.log    128 CURRENT
     2 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_2_cnjfc529_.log    128 ACTIVE
     3 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_3_cnjfc6ly_.log    128 ACTIVE
     4 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cnjfc86f_.log    128 ACTIVE
     5 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cox0ypsz_.log    500 UNUSED

おお!確かにREDOログファイルが追加されました。もう一度パッケージプロシージャを実行してファイルを追加します。

exec rdsadmin.rdsadmin_util.add_logfile('500M');
PL/SQLプロシージャが正常に完了しました。

どうでしょうか。

GROUP# MEMBER                                                MBYTES STATUS
------ ----------------------------------------------------- ------ -------
     1 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_1_cnjfc3ql_.log    128 ACTIVE
     2 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_2_cnjfc529_.log    128 ACTIVE
     3 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_3_cnjfc6ly_.log    128 ACTIVE
     4 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cnjfc86f_.log    128 CURRENT
     5 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cox0ypsz_.log    500 ACTIVE
     6 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cox19j9h_.log    500 UNUSED

2つのREDOログファイルが追加されました。ちなみにこの作業の合間にログスイッチが発生したようで、グループ4がCURRENTに替わっていました。

ログ・スイッチ

次に、ログ・スイッチを実行してみます。

exec rdsadmin.rdsadmin_util.switch_logfile;
PL/SQLプロシージャが正常に完了しました。

確認します。

GROUP# MEMBER                                                MBYTES STATUS
------ ----------------------------------------------------- ------ -------
     1 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_1_cnjfc3ql_.log    128 CURRENT
     2 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_2_cnjfc529_.log    128 ACTIVE
     3 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_3_cnjfc6ly_.log    128 ACTIVE
     4 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cnjfc86f_.log    128 ACTIVE
     5 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cox0ypsz_.log    500 ACTIVE
     6 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cox19j9h_.log    500 ACTIVE

ログ・スイッチは成功です。おっと…ACTIVEがグループ1に移動していました。

REDOログファイル削除

上記ログ・スイッチのプロシージャを何度か繰り返して、新しいREDOロググループをCURRENTにします。

GROUP# MEMBER                                                MBYTES STATUS
------ ----------------------------------------------------- ------ -------
     1 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_1_cnjfc3ql_.log    128 ACTIVE
     2 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_2_cnjfc529_.log    128 ACTIVE
     3 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_3_cnjfc6ly_.log    128 ACTIVE
     4 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cnjfc86f_.log    128 ACTIVE
     5 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cox0ypsz_.log    500 CURRENT
     6 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cox19j9h_.log    500 ACTIVE

ここで、REDOログファイル削除のプロシージャを実行します。

exec rdsadmin.rdsadmin_util.drop_logfile(1);
PL/SQLプロシージャが正常に完了しました。

そして、下記プロシージャを実行します。

exec rdsadmin.rdsadmin_util.checkpoint;

うまく削除できたと思いきや、エラーが発生します。

次のコマンドの開始中にエラーが発生しました : 行 1 -
exec rdsadmin.rdsadmin_util.drop_logfile(1)
エラー・レポート -
ORA-20199: Error in rdsadmin_util.drop_log. ORA-20199: Cannot drop log group: 1 while the status is: ACTIVE
ORA-06512: "RDSADMIN.RDSADMIN_UTIL", 行72
ORA-20199: Cannot drop log group: 1 while the status is: ACTIVE
ORA-06512: 行1

Oracle使いの方は原因がお分かりだと思いますが、REDOログファイルを削除するには、ファイルのステータスがINACTIVEの必要があります。ステータスをINACTIVEにする簡単な方法は、データベースにチェックポイントを発生させることですが、これもALTER SYSTEM文なので、代わりとなるパッケージが無いか探します…ありました。

早速実行してみます。

exec rdsadmin.rdsadmin_util.checkpoint;

どうでしょう…?

GROUP# MEMBER                                                MBYTES STATUS
------ ----------------------------------------------------- ------ -------
     1 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_1_cnjfc3ql_.log    128 INACTIVE
     2 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_2_cnjfc529_.log    128 INACTIVE
     3 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_3_cnjfc6ly_.log    128 INACTIVE
     4 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cnjfc86f_.log    128 INACTIVE
     5 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cox0ypsz_.log    500 CURRENT
     6 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cox19j9h_.log    500 INACTIVE

できました。これでファイルの削除ができるはずです。

exec rdsadmin.rdsadmin_util.drop_logfile(1);
PL/SQLプロシージャが正常に完了しました。

できました。結果を確認します。

GROUP# MEMBER                                                MBYTES STATUS
------ ----------------------------------------------------- ------ -------
     2 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_2_cnjfc529_.log    128 INACTIVE
     3 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_3_cnjfc6ly_.log    128 INACTIVE
     4 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cnjfc86f_.log    128 INACTIVE
     5 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cox0ypsz_.log    500 CURRENT
     6 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cox19j9h_.log    500 INACTIVE

確かにグループ1が削除されています。

これを繰り返して、新しいREDOロググループだけにします。

exec rdsadmin.rdsadmin_util.drop_logfile(2);
exec rdsadmin.rdsadmin_util.drop_logfile(3);
exec rdsadmin.rdsadmin_util.drop_logfile(4);
GROUP# MEMBER                                                MBYTES STATUS
------ ----------------------------------------------------- ------ -------
     5 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cox0ypsz_.log    500 CURRENT
     6 /rdsdbdata/db/ORCL1_A/onlinelog/o1_mf_4_cox19j9h_.log    500 INACTIVE

以上で完了です!

まとめ

RDS Oracleのパフォーマンスチューニングの一環として、REDOログファイルの操作を体験しました。

  • REDOログファイルの初期設定は128MB x 4グループ
  • REDOログファイルに対する以下の操作が、独自のパッケージで提供されている
    • 追加
    • 削除
    • ログ・スイッチ
    • チェックポイント

それから細かい点ですが、プロシージャによるREDOログファイルの追加操作では、グループ番号は自動付与です。以下のルールで付与されるようです。

  • グループ番号は1から順に付与される
  • 既存のグループ番号を飛ばしつつ+1する

引き続き実運用中に遭遇した事象を元に、マニアックな情報をお伝えしたいと思います。それでは、また。