2012/02/03(Friday)
■[mysql] mysqlbinlog なんてやめて show binlog events を使おう
夜中に眠いのに master のディスク容量がいっぱいで、でも binlog 用のスペースがない slave たちはまだ明日起きてから対応するんでも間に合うとき。よくありますよね。
- ほっといてエラーになるよりかはその場しのげる方がマシ
- 多少サービス止めるなり i/o 負荷が高くてもいいから何とかしたい
- 根本的には master 切り替えるしかない
- だが、そこまで元気がない
そんなとき、いままで mysqlbinlog と格闘しながら pos のコピペに注意しつつやってたんですが、 show binlog events という便利コマンドがあることを今更知ったメモです。
基本的な方針
master から絶対に読み込みがないデータを消して、延命することにします。しかし innodb だったりするので単に delete しても容量は減りません。
そこで、えいやとアプリを止めて (or table lock して) 以下のようにすることにします。
CREATE TABLE hoge_history_new LIKE hoge_history; INSERT INTO hoge_history_new SELECT * FROM hoge_history WHERE date >= '2012-01-01'; RENAME TABLE hoge_history TO hoge_history_bak, hoge_history_new TO hoge_history; DROP TABLE hoge_histroy_bak;
ほんとに無停止でやりたいなら trigger で hoge_history_new に double write するとか。しかし trigger 仕込むのでミスするくらいなら、停止した上で停止時間短い方針考えるほうがいい時もあるかかも。
slave は drop してほしくない
これでなんとか master は 10 分停止くらいで drop したぶんの容量が稼げた。しかし slave はまだ容量に多少余裕あるので、できたらこんな drop して欲しくない。と言うよりデータ消しちゃだめじゃん!!
なので、データ消さない slave を 1 つ狙いを定め、上の sql を流す直前に master で show master status を実行し確認した pos まで replication を進めて止めておきます。
slave> STOP SLAVE; slave> START SLAVE UNTIL master_log_file='hoge-bin.000123', master_log_pos=456789;
drop table だけ skip しよう
さて、次は drop table の直前まで replication を進めた上で stop slave し、 sql_slave_skip_counter=1 して drop だけ飛ばしてやりたい。
こんなとき、 pos をどこまで進めればいいかを今までは mysqlbinlog コマンドで調べていました。しかし以下の理由で、絶対もっといい方法あんだろ、と思っていた。
- pos が境界の意味でどっちに含まれているのかよくわからん
- skip_counter は event 単位で、 pos との対応が明確でない
- だいたい出力多すぎで夜中にやると絶対ミスる
なんでドキュメントぷらぷら眺めてたら show binlog events という最強に見やすいコマンドがあったんですね!
つかいかた
まずは slave が何処まで replication しているか調べます。この例では pos=456789 の位置まで実行済み、ということになります。
slave> SHOW SLAVE STATUS\G
...
Master_Log_File: hoge-bin.000123
...
Exec_Master_Log_Pos: 456789
次に pos=456789 からのイベント内容を master で調べます。
master> SHOW BINLOG EVENTS IN 'hoge-bin.000123' FROM 456789 LIMIT 2; +-----------------+--------+------------+-----------+-------------+----------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +-----------------+--------+------------+-----------+-------------+----------------------------------------+ | hoge-bin.000123 | 456789 | Query | 100 | 456901 | use `aho`; drop table hoge_history_bak | | hoge-bin.000123 | 456901 | Intvar | 100 | 457005 | INSERT_ID=91187051 | +-----------------+--------+------------+-----------+-------------+----------------------------------------+ 2 rows in set (0.00 sec)
お、なんとも運がいいことにちょうど次のイベントが drop になってるじゃないですか! ということで slave で 1 イベントをスキップすれば ok。
slave> SET GLOBAL sql_slave_skip_counter=1 slave> START SLAVE;
これで、めでたく master だけデータが欠損した状態に出来ました。後はちゃんと寝てからこの slave に孫を作ってそのまま master に昇格させればよい。
pos と event
改めて考えてみれば、 pos は境界の場所であって、そこに対応する event があるわけじゃないんだよね。
1234567890123456789012345678901234567890 | event1 | event2 | event3 | ^pos=1 ^pos=10 ^pos=25 ^pos=40
たとえば pos=10 のときに 10 に対応する event はなく、前に event1 があって後ろに event2 がある、と。
■[solaris] おや?
https://twitter.com/#!/nslope/status/164802160524136448
なんかひっそりと Solaris11 のソースが公開されてるのかな?? あんまり「キタ━(゚∀゚)━!」と盛り上がってないけど...。
とりあえず du.c 探したけど見つかんない。 2 つめの zip に coreutils や ./osnet/usr/src/lib/libcmd/common/find.c とかは見つかったが。
[追記] まあ
https://twitter.com/#!/syoyo/status/165142247371845632
前からあったらしいですorz
■ [solaris][zfs][memo] compression と recordsize
Solaris 11 11/11 (5.11 11.0) での話。
中身は MySQL の MYD と MYI と frm です。やっぱ InnoDB とか忘れて、基本は bs=128k で生きてたほうが良いような気がする。
send/receive と rsync を状況に合わせて使い分ける場合、 recordsize を設定してたのを忘れてメンテナンス後に変わっちゃう危険があるので、ちまちま分けたくはない。なので公約数的な値を取りたいわけですが、 16k にするかどうかくらいは意識して分けておいたほうがいいかな。
% for i in 2 3 4; do time rsync -av --progress test1/* test$i >/dev/null; done rsync -av --progress test1/* test$i 83.51s user 57.11s system 103% cpu 2:16.36 total rsync -av --progress test1/* test$i 87.93s user 58.11s system 100% cpu 2:25.67 total rsync -av --progress test1/* test$i 79.15s user 49.77s system 99% cpu 2:09.13 total
% zfs list -o space,recordsize,compression,compressratio -r tank NAME AVAIL USED USEDSNAP USEDDS USEDREFRESERV USEDCHILD RECSIZE COMPRESS RATIO tank 20.8T 26.5G 0 123K 0 26.5G 128K off 1.28x tank/test1 20.8T 8.09G 0 8.09G 0 0 128K off 1.00x tank/test2 20.8T 4.45G 0 4.45G 0 0 128K on 1.82x tank/test3 20.8T 8.77G 0 8.77G 0 0 16K off 1.00x tank/test4 20.8T 5.15G 0 5.15G 0 0 16K on 1.76x tank/test5 20.8T 8.05G 0 8.05G 0 0 1M off 1.00x [追記] tank/test6 20.8T 4.37G 0 4.37G 0 0 1M on 1.84x [追記]
cf. http://www.c0t0d0s0.org/archives/5865-SSD,-ZFS,-L2ARC-and-mysql.html
du
余談ですが、 /usr/bin/du のオプション無しって何を表示してるんだろ?
それ以外については、ファイルサイズの合計ではなく、そのディレクトリ以下に含まれるファイルたちの disk usage を出してくれてるみたい。
% /usr/bin/du test* 16957022 test1 9331071 test2 18395314 test3 10803173 test4
% /usr/bin/du -h test* 8.1G test1 4.4G test2 8.8G test3 5.2G test4
% /usr/gnu/bin/du test* 8478511 test1 4665536 test2 9197657 test3 5401587 test4
% /usr/gnu/bin/du -h test* 8.1G test1 4.5G test2 8.8G test3 5.2G test4


