読者です 読者をやめる 読者になる 読者になる

文系プログラマによるTIPSブログ

文系プログラマ脳の私が開発現場で学んだ事やプログラミングのTIPSをまとめています。

AmazonRDS:ログ関連とログローテート

mysql

クラウドDBとして有名なAmazonRDSのログについてのお話。

RDSはサーバのファイルシステムに直接アクセスする事ができません。
つまり、通常のクエリログ・slow-query-logをファイルとして出力できず、テーブル出力のみとなります。
ログテーブルは、mysqlスキーマにあり、対応は以下のようになっています。

クエリログ・・・・mysql.general_log(engine = csv)。PK・KEYの設定無し。
slow-query-log・・mysql.slow_log(engine = csv)。PK・KEYの設定無し。

まず、デフォルトでクエリログとslow-query-logは無効となっているので、
rds-modify-db-parameter-group パラメータグループ名 -p "name=general_log, value=1, method=immediate"
こんな感じで有効にする必要があります。

これらのテーブルで問題なのは、更新クエリの実行権限が無い、という点です。参照権限のみです。
つまり、ログをdelete・truncateする事はできません。ではどうやってログの世代管理をするか。
なんと、世代管理用のストアドプロシージャが用意されています。

mysql> select name from mysql.proc where name like 'rds_%';
+------------------------+
| name                   |
+------------------------+
| rds_kill               |
| rds_kill_query         |
| rds_rotate_general_log | ← これがクエリログの世代管理
| rds_rotate_slow_log    | ← これがslow-query-logの世代管理
+------------------------+

ストアドが用意してあるのですが、ちょっと問題が・・それは、
誤って2回連続ストアドを実行するとログが全削除される
という点です。これは怖い。ストアドの中身は以下のようになっています。

◆ ストアド実行前
general_log(ログが入っている)
◆ストアド実行1回目
general_log2をcreate。
general_log_backupをdrop。
general_log ーrename→ general_log_backup。(general_logがbackupになる)
general_log2 ーrename→ general_log。

こうなります。つまり、general_log のログは general_log_backup になります。
これをよく見ると解りますが、general_log_backupをdropするので、2回連続実行すると、綺麗さっぱりログが消えます・・

世代管理として使えるテーブルは、general_log と general_log_backup の2種類のみ。
そしてこれらのテーブルにはインデックスが設定されていない。
インデックスが無いということは、1000件前後しかデータを入れないだろう、という事なのでしょう。
ということは、1000件たまったらストアド実行で世代管理、みたいなスクリプトを書くのがいいと思われます。

まあこの辺が面倒なら、別のインスタンスに同構成のスキーマ用意して、そっちで管理する手もありますね。
↓こんなのを毎日cronで実行するとか。

create table if not exists hoge.general_log like mysql.general_log;
insert into hoge.general_log select * from mysql.general_log;
call rds_rotate_general_log();