犯人はLocal by Flywheelだった。WordPressのローカル環境を立てるあのアプリが動かしているMySQLの中で、誰も使っていないバイナリログが37GBまで育っていた。
まず何が重いのか
du で上から順に潰していったら ~/Library/Application Support/Local が81GBあって、それとは別に ~/Local Sites にも53GB積まれていた。合わせて134GB。1TB弱のディスクの15%近くを、このアプリひとつで持っていっている計算になる。
Localは run/ の下にサイトごとのランタイムを置いている。覗いた。
38G Local/run/site-a
35G Local/run/site-b
1.2G Local/run/site-c
1.1G Local/run/site-d
912M Local/run/site-e
上2つだけ桁が違う。さらに掘ると、どちらも中身は mysql/data がほぼ全部を占めていた。
1GBのファイルが39本
中を見て察した。
1.0G binlog.000147
1.0G binlog.000146
1.0G binlog.000145
1.0G binlog.000144
1.0G binlog.000143
MySQLのバイナリログ。1ファイルきっちり1GBで切られたものが39本並んでいて、合計すると37GBになる。
binlogというのは、レプリケーションとポイントインタイムリカバリのために更新系のクエリを片っ端から記録していく仕組みで、本番のDBなら当然要る。ローカル開発のWordPressに要るかというと、レプリカを繋いでいるわけでもないし、ローカルのDBを3日前の状態まで巻き戻したいと思ったことも一度もないので、まったく要らない。
厄介なのは、MySQL 8.0がbinlogをデフォルトで有効にしていて、Localがその設定をそのまま使っているところだ。つまり何もしなければ、全サイトで永遠に積み上がっていく。放っておいた俺が悪いとも言えるが、増えていることに気づく手段が特にない。
溜まった分を消す
まずLocalでそのサイトを止める。MySQLが動いたままデータディレクトリのファイルを消すのは行儀が悪いので、必ずStopしてから触る。
止めたら、あとは消すだけ。<siteId> は run/ の下のディレクトリ名で、どれがどのサイトかはLocalのサイト設定から辿れる。
P=~/Library/"Application Support"/Local/run/<siteId>/mysql/data
find "$P" -maxdepth 1 -name "binlog.0*" -exec /bin/rm -f {} +
: > "$P/binlog.index"
binlog.index はどのbinlogファイルが存在するかの一覧を持っているファイルなので、これだけは消さずに空にしておく。消したはずのファイルが載ったままだと次の起動で怒られる。
38GBが565MBになった。あとはLocalでサイトを起動し直せば、何事もなかったように動く。
二度と積まれないようにする
消して終わりにすると半年後にまた同じことになるので、各サイトの conf/mysql/my.cnf の [mysqld] に1行入れておく。
disable-log-bin
ただしこれは既存サイトにしか効かない。新しく作るサイトにも最初から入れておきたいところだが、Localはサイト作成時にHandlebarsのテンプレートからmy.cnfを生成しているので、効かせたければそっちを直してやる必要がある。
~/Library/Application Support/Local/lightning-services/mysql-*/conf/my.cnf.hbs
ここの [client] セクションの直前に同じ1行を置いておけば、以降作るサイトは最初からbinlog無効で生まれてくる。俺の環境には 8.0.16 / 8.0.35 / 8.4.0 の3種類が入っていたので全部やった。既存11サイトのmy.cnfもまとめてパッチした。
既存サイトのmy.cnfをLocalが勝手に再生成することはない。あるサイトに1年以上前に手書きした secure-file-priv="" がそのまま残っていたので、手を入れても消えないのは確認できている。
MariaDBには入れるな
disable-log-bin はMySQLのオプションだ。MariaDBはこれを知らないので書くとmysqldが起動に失敗するし、そもそもMariaDBはbinlogがデフォルトで無効なので入れる必要もない。
サイトごとのDB種別は sites.json の services.mysql で分かるが、俺のところは全11サイトがMySQL 8.0.35で揃っていたので、種別を気にすることなく全部へ入れられた。
設定が通るかどうかは、サーバを起動しなくても確認できる。
mysqld --defaults-file=<site my.cnf> --validate-config
exit 0 なら大丈夫。念のため止まっているサイトを実際に起動して SHOW VARIABLES LIKE 'log_bin' を叩いてみたら OFF になっていたし、起動から停止までのあいだにbinlogファイルは1本も作られなかった。ひとつだけ紛らわしいのが binlog.index で、これは空のまま残る。binlog.* でgrepすると1件ヒットして焦る。
結局
ローカル開発のMySQLにbinlogは要らない。Localを使っているなら、ディスクが泣いてから慌てるより、いま my.cnf.hbs へ1行入れておくほうが早い。
あと、消したはずなのに空きが増えないときは、まずAPFSのローカルスナップショットを疑ったほうがいい。消したものがまだ消えていないだけで、大抵は自分のせいじゃない。

コメント