クラウド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();