今の案件に触れてからの自分の低能ぶりの凄まじさに自ら恐怖を禁じ得ず、椅子から転げ落ちて失禁しそうなmix3です。
レプリケーション
今の案件ではDBにMySQLを使いレプリケーションを使って負荷分散しております。(レプリケーション必要無いぐらいの負荷だよね、とかインフラの方に言われてまた失禁しそうです)
レプリケーションというのはリアルタイムに複製する技術のこと?上手く説明出来ませんが、まあWebサービスなんかだと書き込みより読み込みの方が圧倒的に割合が大きいらしく、マスターとその複製のスレーブにDBを分けて、書き込みはマスターへ、読み込みは複製のスレーブへ処理を振り分ける事で負荷を分散したりします。
スレーブ遅延
レプリケーションというのはリアルタイムな複製技術なので、基本的にはマスターとスレーブは同期が取れているハズですが、サーバの負荷状況によっては同期がとれていない状態になったりします。スレーブ遅延というものです。
レプリケーション下での更新処理
たとえばインクリメント的なアトミックな更新であればスレーブは関わらないので問題ないと思います。
UPDATE table SET column + 1 WHERE id = ?
そうではなくスレーブから読み込みをし、マスターに書き込みをするような処理をしてしまうと、スレーブが遅延していた場合に古い情報をもとに更新をしてしまい不整合が発生するなどあまりよろしくない状態になります
SELECT hoge FROM table_1 WHERE id = ?
スレーブから取ってきたhogeが古いものだと、その後のUPDATEでそのhogeを使うのは当然よろしくない
×UPDATE table_2 SET column = WHERE id = ?
なので、そういったSELECT>UPDATEのような更新処理の場合は、SELECTもスレーブからではなくマスターからするようにしないといけせん。
ようするにスレーブ遅延による不整合が発生したということ
です。気をつけましょう。
MySQL::Sandbox と Percona Toolkit(旧Maatkit)のpt-slave-delay
こういうスレーブ遅延によるバグは開発環境では気づきにくかったりします。負荷の掛かっていない開発環境ではスレーブ遅延は発生しづらいでしょうし、そもそもDB構成が本番と違っていてレプリケーションされてなかったりすることも多いでしょう。
が、最近は便利になった物で、cpanに上がっているMySQL::SandboxとPercona Toolkit(旧Maatkit)なるツールを使うと割と簡単にレプリケーション環境とスレーブ遅延を再現出来ます。というかMySQL::SandboxもPercona Toolkit(旧Maatkit)結構前からあるので最初から使っておけという感じですね。(正月にデータが吹っ飛ぶ前は実は使ってたりしてたんですけどね...)
MySQL::Sandbox
Install
- cpanm MySQL::Sandbox
How to use
- SANDBOX_AS_ROOT=1 make_replication_sandbox -r master_data --how_many_slaves 1 --sandbox_base_port 11111 download/mysql-5.1.66-linux-x86_64-glibc23.tar.gz
- rootで作業するとSANDBOX_AS_ROOT=1を使わないと怒られるけどそもそもrootで作業するなという話
- sandboxes/master_data/以下にマスター(port: 11111, socket: /tmp/mysql_sandbox11111.sock)スレーブ(port: 11112, socket: /tmp/mysql_sandbox11112.sock)が出来る
- perl -MDBI -e 'DBI->connect("dbi:mysql:test:mysql_socket=/tmp/mysql_sandbox11111.sock", "msandbox", "msandbox")'
- port指定での接続方法は分からなかった。できなくは無いと思うけど
init script
- 以下のような感じで書いてみたがうまくいかん
- 落とし忘れるとsocketファイルが残って次回起動時に残念な事になるので出来ればなんとかしたい
#!/bin/sh
# chkconfig: 2345 65 35
# description: sandbox_action
# Source function library.
. /etc/rc.d/init.d/functions
# Get config.
. /etc/sysconfig/network
# Check that networking is up.
if [ ${NETWORKING} = "no" ]
then
exit 0
fi
prog="sandbox_action"
case "$1" in
start)
echo -n "Starting $prog: "
sandbox_action start
success
echo
;;
stop)
echo -n "Stopping $prog: "
sandbox_action stop
success
echo
;;
status)
sandbox_action status
;;
*)
echo $"Usage: $prog {start|stop|status}"
exit 1
esac
exit 0
Percona Toolkit(旧Maatkit)
Install
- Perconaからtarを落としてきて、perl Makefile.PL, make && make install
- rpmは依存関係がうるさいのでtarからのほうが良いと思う
How to use
- pt-slave-delay -u msandbox -p msandbox --socket /tmp/mysql_sandbox11112.sock
- --daemonize オプションもある