MySQL
2011年11月04日
環境構築する為の準備運動
ここ数日のエントリは、本エントリの環境を構築する為の検証作業。
準備運動が終わったので、いよいよ結合する時が来た。 この構成で環境構築する事が本エントリの主目的であって、信頼性を問うのは議論の対象外である。
検証環境
- RHEL 6.0 / CentOS 6.0
- ucarp 1.5.2-1.el6
- nfs-utils 1.2.2-7.el6
- mysql-server 5.1.52-1.el6_0.1
要件定義
- mysql + nfs
- 隣のノードの/var/lib/mysqlをdatadirとしてMySQLを起動
- mysqlクライアントはVIP指定でmysqlサーバへ接続
- ucarp
- failoverによりVIPが切り替わる
- 自動failbackは不要
- 手動failbackで良い
前提条件
- mysql datadir on nfsまで作業が完了している事
作業概要
- ucarpの設定ファイルを作成
- upscript, downscriptを配置
- ucarpを起動
- サービスの状態を確認
環境定義
| 用途 | IPアドレス | nfsディレクトリ | NIC | ucarp状態 |
|---|---|---|---|---|
| nfsクライアント | 192.0.2.12/24 | export: /var/lib/mysql/ | eth0 | master |
| nfsサーバ | 192.0.2.13/24 | mount: /var/lib/mysql/ | backup | |
| mysqlサーバ | 192.0.2.254/24 | - | - |
事前作業
作業前にucarpを停止しておく。 これは後の作業で更新する設定により、ucarp停止時の振る舞いが変化するのを避ける為。 必ず、backup側のucarpを停止してから、master側のucarpを停止する事。
- ucarp-backup
# /etc/init.d/ucarp stop
- ucarp-master
# /etc/init.d/ucarp stop
ucarpがmysqlのサービス起動・停止を行うので、mysqldがSysV initやupstartによって管理され無い事を確認しておく事。
# chkconfig --list mysqld mysqld 0:off 1:off 2:off 3:off 4:off 5:off 6:off
作業内容
Linux + ucarpによるサーバ冗長化で触れた様に、upscript/downscriptに冗長化したいアプリケーションの起動停止処理を記述出来る。nfsマウントとmysqlの起動停止を記述しておけば今回の要件を満たせる。
ucarp共通
upscriptとdownscriptを配置するディレクトリを作成。推奨されている配置先ディレクトリが定められてないので、今回は/etc/ucarp/vip-{up,down}.d/ に配置する。
# mkdir /etc/ucarp/vip-up.d # mkdir /etc/ucarp/vip-down.d
ucarp-masterに設定ファイルとupscript/downscriptを配置
master側にはnfsマウントに関する処理が入る。
- /etc/ucarp/vip-001.conf
SOURCE_ADDRESS=192.0.2.12 ID=001 BIND_INTERFACE=eth0 VIP_ADDRESS=192.0.2.254 OPTIONS="--shutdown --preempt" UPSCRIPT=/etc/ucarp/vip-up.d/mysql-master DOWNSCRIPT=/etc/ucarp/vip-down.d/mysql-master
- /etc/ucarp/vip-up.d/mysql-master
#!/bin/sh exec 2>/dev/null /sbin/ip address add "$2"/32 dev "$1" /bin/mount -t nfs 192.0.2.13:/var/lib/mysql/ /var/lib/mysql/ /etc/init.d/mysqld start
- /etc/ucarp/vip-down.d/mysql-master
#!/bin/sh exec 2>/dev/null /sbin/ip address del "$2"/32 dev "$1" /etc/init.d/mysqld stop /bin/umount /var/lib/mysql/
ucarp-backupに設定ファイルとupscript/downscriptを配置
backup側はmysql datadirがローカルディスクであるため、mount処理が無い。
- /etc/ucarp/vip-001.conf
SOURCE_ADDRESS=192.0.2.13 ID=001 BIND_INTERFACE=eth0 VIP_ADDRESS=192.0.2.254 OPTIONS="--shutdown --preempt" UPSCRIPT=/etc/ucarp/vip-up.d/mysql-backup DOWNSCRIPT=/etc/ucarp/vip-down.d/mysql-backup
- /etc/ucarp/vip-up.d/mysql-backup
#!/bin/sh exec 2>/dev/null /sbin/ip address add "$2"/32 dev "$1" /etc/init.d/mysqld start
- /etc/ucarp/vip-down.d/mysql-backup
#!/bin/sh exec 2>/dev/null /sbin/ip address del "$2"/32 dev "$1" /etc/init.d/mysqld stop
ucarpを起動
ucarp停止処理の順番とは逆で、master側ucarpを起動してから、backup側ucarpを起動する事。
- ucarp-master
# /etc/init.d/ucarp start
- ucarp-backup
# /etc/init.d/ucarp start
ucarp起動後の状態確認
master側でmysqlがサービスされていれば良い。大まかに確認するには、下記内容で問題ないはずだ。
ucarp-master
- VIPが割り当てられている事
# ip addr show eth0 | grep -w inet inet 192.0.2.12/24 brd 192.0.2.255 scope global eth0 inet 192.0.2.254/32 scope global eth0 - /var/lib/mysqlにnfsマウントされている事
# mount -t nfs 192.0.2.13:/var/lib/mysql/ on /var/lib/mysql type nfs (rw,vers=4,addr=192.0.2.13,clientaddr=192.0.2.12)
- mysqlが起動している事
# /etc/init.d/mysqld status mysqld (pid XXX) is running...
ucarp-backup
- VIPが割り当てられてない事
# ip addr show eth0 | grep -w inet inet 192.0.2.13/24 brd 192.0.2.255 scope global eth0 - mysqlが起動してない事
# /etc/init.d/mysqld status mysqld is stopped
failoverとfailbackを確認
ucarp-master, ucarp-backupのucarpを起動・停止させればmysqlとVIPが切り替わる。 failover/failbackの手順はLinux + ucarpによるサーバ冗長化を参照の事。手元の環境ではfailover/failbackする事を確認出来ている。
必要に応じて接続許可設定
追加設定無しではVIP指定で接続出来ないはずなので、GRANTで許可を付与しておく。
# mysql -uroot mysql> GRANT ALL PRIVILEGES ON *.* TO root@'%' WITH GRANT OPTION; mysql> FLUSH PRIVILEGES;
あとがき
ucarpを使えば簡単に冗長化させる事が可能だ。
秀和システム
売り上げランキング: 190665
信頼性はどうであれ、共有ディスクを使ったMySQL
nfsマウント領域にmysql datadirを配置し、mysqlを起動させる。
検証環境
- RHEL 6.0 / CentOS 6.0
- nfs-utils 1.2.2-7.el6
- mysql-server 5.1.52-1.el6_0.1
要件定義
- 隣のノードの/var/lib/mysqlをdatadirとしてMySQLを起動
作業概要
- nfsサーバ
- /var/lib/mysql を公開領域として設定
- nfsクライアント, mysqld
- nfsサーバの/var/lib/mysqlを、自身の/var/lib/mysqlにnfsマウント
- mysqlを起動
環境定義
| 用途 | IPアドレス | nfsディレクトリ |
|---|---|---|
| nfsクライアント | 192.0.2.12/24 | /var/lib/mysql/ |
| nfsサーバ | 192.0.2.13/24 | /var/lib/mysql/ |
事前作業
NFSの設定作業は ファイルサーバ構築 を参照の事。公開ディレクトリとマウントポイントを、それぞれ /var/lib/mysql に置き換えれば良い。
- 共通
-
# yum -y install mysql-server
- nfsサーバ
-
# echo '/var/lib/mysql 192.0.2.0/24(rw)' >> /etc/exports # exportfs -ra
作業内容
事前作業にて、nfsサーバの設定が終わってるものとする。
SELinuxを無効化
mysql datadirがnfsマウントされているとmysqldが起動しない。
# /etc/init.d/mysqld start chown: changing ownership of `/var/lib/mysql': Operation not permitted chmod: changing permissions of `/var/lib/mysql': Operation not permitted MySQL Daemon failed to start. Starting mysqld: [FAILED]
nfsマウントしたmysql datadir領域でもmysqlが起動する様にSELinuxを設定するのが良いのだろうが、本題はmysqlを起動させる事なのでSELinux無効化で済ませる。
# cp -pi /etc/sysconfig/selinux /etc/sysconfig/selinux.0 # diff /etc/sysconfig/selinux.0 /etc/sysconfig/selinux 7c7 < SELINUX=enforcing --- > SELINUX=disabled
システム再起動
# reboot
SELinuxが無効化さていればmysqlが起動するはず。
mysql datadirをnfsマウント
mountコマンドでnfsマウント。
# mount -t nfs 192.0.2.13:/var/lib/mysql /var/lib/mysql
必要に応じて/etc/fstabにマウントエントリを追加しておく事。
mysql起動
mysqlを起動
# /etc/init.d/mysqld start
mysqlが起動してる事を確認
# mysqladmin -uroot ping mysqld is alive
mysql接続して内容を確認
# mysql -uroot mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | test | +--------------------+ 3 rows in set (0.06 sec)
必要に応じてmysqlをサービス起動対象に追加しておくこと。
# chkconfig --list mysqld mysqld 0:off 1:off 2:off 3:off 4:off 5:off 6:off
あとがき
疑わしい挙動をする時はSELinuxを無効化か
秀和システム
売り上げランキング: 190665
2009年05月15日
[Wakame] Amazon EC2 API Toolsを使ってMySQL Slaveを作る (2/n) の続編
前回予告した通り、今回はMySQLのdatadirにAmazon EBS Volumeをマウントした設定。
今回の作業前提条件は、
- MySQL Master
- master用my.cnfが存在する
- datadir = /home/wakame/mysql/data/
- server-id = 1
- log_bin
- master用my.cnfが存在する
- MySQL Slave
- slave用my.cnfが存在する
- datadir = /home/wakame/mysql/data-slave/
- server-id = 2
- slave用my.cnfが存在する
6つのファイル
今回使うのは6つのファイル。
- _wakame-common.sh
- 共通設定
- wakame-ebs-mysql-master-create-volume.sh
- Amazon EBS Volume作成
- wakame-ebs-mysql-master-init.sh
- MySQLのdatadirを初期化
- ※今回初登場
- wakame-ebs-mysql-master-add-repl-user.sh
- MySQLのレプリケーション用MySQLアカウント作成
- ※今回初登場
- wakame-ebs-mysql-master-make-snapshot.sh
- Master datadirからAmazon EBS Snapshot作成
- ※今回初登場
- wakame-ebs-mysql-slave-restore.sh
- Amazon EBS Snapshotからslave用datadir作成
- ※今回初登場
前回登場しているファイルは省略。
▼wakame-ebs-mysql-master-init.sh
#!/bin/sh
#
# http://blog.hansode.org/
# 2009.05.12
#
##
## variables
##
# common
pwd=$(cd $(dirname $0) && pwd)
[ -f ${pwd}/_wakame-common.sh ] && . ${pwd}/_wakame-common.sh
df ${ebs_master_dev} || exit 1
[ -d ${ebs_master_mnt} ] || exit 1
chown mysql:mysql ${mysqld_master_dir}
mysql_install_db --datadir=${mysqld_master_dir}
exit 0
▼wakame-ebs-mysql-master-add-repl-user.sh
#!/bin/sh
#
# http://blog.hansode.org/
# 2009.05.12
#
##
## variables
##
# common
pwd=$(cd $(dirname $0) && pwd)
[ -f ${pwd}/_wakame-common.sh ] && . ${pwd}/_wakame-common.sh
[ -z "${mysqld_master_acl}" ] && { echo "please set mysqld_master_acl"; exit 1; }
echo "GRANT REPLICATION SLAVE, REPLICATION CLIENT, RELOAD ON *.* TO '${mysqld_master_info_user}'@'${mysqld_master_acl}' IDENTIFIED BY '${mysqld_master_info_pass}';" | mysql_command
echo "FLUSH PRIVILEGES;" | mysql_command
exit 0
▼wakame-ebs-mysql-master-make-snapshot.sh
#!/bin/sh
#
# http://blog.hansode.org/
# 2009.05.12
#
##
## variables
##
# common
pwd=$(cd $(dirname $0) && pwd)
[ -f ${pwd}/_wakame-common.sh ] && . ${pwd}/_wakame-common.sh
# ebs_master_volume=
ebs_master_volume=$(ec2-describe-volumes | grep ${ec2_instance_id} | grep ${ebs_master_dev} | grep attached | awk '{print $2}')
[ -z "${ebs_master_volume}" ] && { echo not mounted: ${ebs_master_dev}; exit 1; }
echo ${ebs_master_volume}
echo
# connect test
echo "SHOW MASTER STATUS" | mysql_command >/dev/null || {exit 1;}
#
echo "... flush tables with read lock;";
echo "FLUSH TABLES WITH READ LOCK;" | mysql_command
#
echo "... show master status;";
mysqld_master_status=$(echo "SHOW MASTER STATUS;" | mysql_command)
set ${mysqld_master_status}
mysqld_master_binlog_file=$1
mysqld_master_binlog_pos=$2
#
echo "... make master.info"
cat <<EOS > ${mysqld_master_dir}/master.info
14
${mysqld_master_binlog_file}
${mysqld_master_binlog_pos}
${mysqld_master_info_host}
${mysqld_master_info_user}
${mysqld_master_info_pass}
${mysqld_master_info_port}
60
0
EOS
#
chmod 0644 ${mysqld_master_dir}/master.info
chown mysql:mysql ${mysqld_master_dir}/master.info
#
echo "$ ec2-create-snapshot ${ebs_master_volume}"
#
ebs_master_snapshot_id=$(ec2-create-snapshot ${ebs_master_volume} | awk '{print $2}')
[ -z "${ebs_master_snapshot_id}" ] && { exit 1; }
#
for i in 1 2 3 4 5 6 7 8 9 10; do
echo -n ". "
ec2-describe-snapshots | grep ${ebs_master_snapshot_id} | grep completed -q && break
sleep 1
done
echo
#
echo "... unlock tables;";
echo "UNLOCK TABLES;" | mysql_command
echo ">>> snapshot_id = ${ebs_master_snapshot_id}"
exit 0
▼wakame-ebs-mysql-slave-restore.sh
#!/bin/sh
#
# http://blog.hansode.org/
# 2009.05.12
#
##
## variables
##
# local
ebs_master_snapshot_id=$1
[ -z "${ebs_master_snapshot_id}" ] && { echo "usage: $0 [snapshot-id]"; exit 1; }
# common
pwd=$(cd $(dirname $0) && pwd)
[ -f ${pwd}/_wakame-common.sh ] && . ${pwd}/_wakame-common.sh
## check phase
[ -b "${ebs_slave_dev}" ] && { echo "already attached: ${ebs_slave_dev}"; exit 1; }
df ${ebs_slave_dev} >/dev/null 2>&1 && { echo "already mounted: ${ebs_slave_dev}"; exit 1; }
## EC2 instance
# create volume
ebs_slave_volume=$(ec2-create-volume --snapshot ${ebs_master_snapshot_id} -z ${ec2_zone} | awk '{print $2}')
[ -z "${ebs_slave_volume}" ] && { echo "can't create volume"; exit 1; }
for i in 1 2 3 4 5 6 7 8 9 10; do
echo -n ". "
ec2-describe-snapshots | grep ${ebs_master_snapshot_id} | grep completed -q && break
sleep 1
done
echo
# attache volume
ec2-attach-volume -d ${ebs_slave_dev} -i ${ec2_instance_id} ${ebs_slave_volume}
for i in 1 2 3 4 5 6 7 8 9 10; do
echo -n ". "
sync
[ -b ${ebs_slave_dev} ] && break
sleep 1
done
# mount ...
[ -z "${ebs_slave_mnt}" ] && { echo "please set ebs_slave_mnt"; exit 1; }
[ -d "${ebs_slave_mnt}" ] || mkdir ${ebs_slave_mnt}
mount ${ebs_slave_dev} ${ebs_slave_mnt} >/dev/null 2>&1
mount | grep ${ebs_slave_dev}
df ${ebs_slave_dev} >/dev/null 2>&1 || { echo "not available: ${ebs_slave_dev}"; exit 1; }
echo
# current volume?
ec2-describe-volumes ${ebs_slave_volume}
# done
exit 0
スクリプトの準備
前回同様の作業ディレクトリへ移動
# cd work/wakame
初登場スクリプト2つをそれぞれコピー&ペースト
# cat > wakame-ebs-mysql-master-init.sh (コピー&ペースト) ^D # cat > wakame-ebs-mysql-master-add-repl-user.sh (コピー&ペースト) ^D # cat > wakame-ebs-mysql-master-make-snapshot.sh (コピー&ペースト) ^D # cat > wakame-ebs-mysql-slave-restore.sh (コピー&ペースト) ^D
実行可能状態にしておく
# chmod +x ./wakame-ebs-mysql-master-init.sh # chmod +x ./wakame-ebs-mysql-master-add-repl-user.sh # chmod +x ./wakame-ebs-mysql-master-make-snapshot.sh # chmod +x ./wakame-ebs-mysql-slave-restore.sh
動作実行例
MySQL Masterのdatadir用にAmazon EBS Volumeを作成
master# ./wakame-ebs-mysql-master-create-volume.sh $ ec2-create-volume -z us-east-1b -s 1 ebs_master_volume:vol-e058ba89 $ ec2-attach-volume -d /dev/sdm -i i-f9047990 vol-e058ba89 ATTACHMENT vol-e058ba89 i-f9047990 /dev/sdm attaching 2009-05-15T03:37:49+0000 . . $ yes | mkfs -t ext3 /dev/sdm >/dev/null 2>&1 /dev/sdm on /home/wakame/mysql/data type ext3 (rw)
MySQL Masterのdatadir用を初期化
master# ./wakame-ebs-mysql-master-init.sh
レプリケーション用MySQLアカウントを追加
master# ./wakame-ebs-mysql-master-add-repl-user.sh
MySQL Masterのmysqldを起動
master# mysql start
MySQL MasterのdatadirからAmazon EBS Snapshotを作成
master# ./wakame-ebs-mysql-master-make-snapshot.sh vol-e058ba89 ... flush tables with read lock; ... show master status; ... make master.info $ ec2-create-snapshot vol-e058ba89 ... unlock tables; . >>> snapshot_id = snap-50c73f39
例では、snapshotのIDが「snap-50c73f39」となった。
先に生成したAmazon EBS Snapshotからslave用datadir作成。
この時、snapshot IDが必要となる。
slave# ./wakame-ebs-mysql-slave-restore.sh snap-50c73f39 . ATTACHMENT vol-3e5ebc57 i-1344387a /dev/sdn attaching 2009-05-15T07:19:14+0000 . . /dev/sdn on /home/wakame/mysql/data-slave type ext3 (rw) VOLUME vol-3e5ebc57 1 snap-50c73f39 us-east-1b in-use 2009-05-15T07:19:01+0000 ATTACHMENT vol-3e5ebc57 i-1344387a /dev/sdn attached 2009-05-15T07:19:14+0000
MySQL Slaveのmysqldを起動
slave# mysql start
レプリケーションの確認
ここはざっくり省略。
- MySQL Master
- 「SHOW MASTER STATUS」で状態を確認
- MySQL Slave
- 「SHOW SLAVE STATUS」で状態を確認
- IOスレッド、SQLスレッドが「YES」である事
- Masterのbinlogポジションと同値である事
本シリーズは3回で終わり
AWSを使ったMySQLレプリケーション作成と設定は今回で終わり。
- [Wakame] Amazon EC2 API Toolsを使ってMySQL Slaveを作る (1/n)
- [Wakame] Amazon EC2 API Toolsを使ってMySQL Slaveを作る (2/n)
- [Wakame] Amazon EC2 API Toolsを使ってMySQL Slaveを作る (3/3)
シリーズを振り返る
Wakameに組み込む為の手順の確認で作り始めたスクリプト。
このスクリプト単体でも意外と便利なのでアウトプットしてみた。
1人でも良いので、誰かの役に立てればアウトプットした意味がある。
AWS(Amazon Web Service)を使うと、いろいろな事が簡単に出来る事を実感した。
今回の様に、一度スクリプトを作ってしまえば、その後の作業は物凄く単純化される。
AWSに惚れ直した。
今後、色々なデベロッパーによって面白い使い方がされて行くだろう。
その面白い使い方の1つが「Wakame」になるはずだ!
オライリージャパン
売り上げランキング: 137177
オライリージャパン
売り上げランキング: 101715
Pragma
売り上げランキング: 6573
2009年05月14日
[Wakame] Amazon EC2 API Toolsを使ってMySQL Slaveを作る (1/n) の続編
前回予告した通り、今回はAmazon EBSのVolume操作するシェルスクリプト。
今回の作業前提条件は、
- Amazon EC2 API Toolsがインストールされ、動作する事
- さらに、rootアカウントでAmazon EC2 API Toolsが動作する事
※前回はUNIXアカウント「ubuntu」で作業を行っていたので、rootにて同じ作業をするだけ。
3つのファイル
今回使うのは3つのファイル。
- _wakame-common.sh
- 共通設定
- wakame-ebs-mysql-master-create-volume.sh
- Amazon EBS Volume作成
- wakame-ebs-mysql-master-delete-volume.sh
- Amazon EBS Volume削除
▼_wakame-common.sh
# Amazon EBS
ebs_master_size=1 # 1G
ebs_master_fstype=ext3 # filesystem
ebs_master_dev=/dev/sdm # device name
ebs_master_mnt=/home/wakame/mysql/data # mount point
ebs_slave_dev=/dev/sdn # device name
ebs_slave_mnt=/home/wakame/mysql/data-slave # mount point
# Amazon EC2
ec2_instance_id=$(curl -s -f --retry 3 http://169.254.169.254/2008-02-01/meta-data/instance-id/)
ec2_zone=$(curl -s -f --retry 3 http://169.254.169.254/2008-02-01/meta-data/placement/availability-zone/)
ec2_local_ipv4=$(curl -s -f --retry 3 http://169.254.169.254/2008-02-01/meta-data/local-ipv4)
# mysqld master
mysqld_master_mnt=${ebs_master_mnt}
mysqld_master_dir=${mysqld_master_mnt} # datadir
mysqld_master_admin_host=127.0.0.1 # MySQL Masterのホスト名(or IPアドレス)
mysqld_master_admin_user=root # MySQL Masterの管理ユーザー名
mysqld_master_acl='%' # MySQL Masterへの接続元制限
# master.info
mysqld_master_info_host=${ec2_local_ipv4} # Slaveから見たMasterのホスト名(or IPアドレス)
mysqld_master_info_user=wakame-repl # レプリケーション用ユーザー名
mysqld_master_info_pass=wakame-slave # レプリケーション用パスワード
mysqld_master_info_port=3306 # Slaveから見たMasterのポート番号
# この例では、ホスト名とユーザー名の指定のみ行っている
# 必要に応じて -p などを追加して下さい
mysql_command() {
cat | mysql \
-h${mysqld_master_admin_host} \
-u${mysqld_master_admin_user} \
-s
# -p${mysqld_master_admin_pass} \
# -P${mysqld_master_admin_port} \
}
▼wakame-ebs-mysql-master-create-volume.sh
#!/bin/sh
#
# http://blog.hansode.org/
# 2009.05.12
#
##
## variables
##
# common
pwd=$(cd $(dirname $0) && pwd)
[ -f ${pwd}/_wakame-common.sh ] && . ${pwd}/_wakame-common.sh
##
## check phase
##
[ -b "${ebs_master_dev}" ] && { echo "already attached: ${ebs_master_dev}"; exit 1; }
df ${ebs_master_dev} >/dev/null 2>&1 && { echo "already mounted: ${ebs_master_dev}"; exit 1; }
# create volume ...
[ -z "${ebs_master_size}" ] && { echo "plese set ebs_master_size"; exit 1; }
echo "$ ec2-create-volume -z ${ec2_zone} -s ${ebs_master_size}"
ebs_master_volume=$(ec2-create-volume -z ${ec2_zone} -s ${ebs_master_size} | awk '{print $2}')
sleep 1
[ -z "${ebs_master_volume}" ] && { echo "can't get ebs_master_volume"; exit 1; }
echo ebs_master_volume:${ebs_master_volume}
echo
# attach ebs_master_volume ...
[ -z "${ebs_master_dev}" ] && { echo "please set ebs_master_dev"; exit 1; }
[ -z "${ebs_master_fstype}" ] && { echo "please set ebs_master_fstype"; exit 1; }
mount | grep -q ${ebs_master_dev} && { echo "not mounted: ${ebs_master_dev}"; exit 1; }
echo "$ ec2-attach-volume -d ${ebs_master_dev} -i ${ec2_instance_id} ${ebs_master_volume}"
ec2-attach-volume -d ${ebs_master_dev} -i ${ec2_instance_id} ${ebs_master_volume}
echo
for i in 1 2 3 4 5 6 7 8 9 10; do
echo -n ". "
sync
[ -b "${ebs_master_dev}" ] && break
sleep 1
done
echo
[ -b "${ebs_master_dev}" ] || { echo "not available: ${ebs_master_dev}"; exit 1; }
# format ...
echo "$ yes | mkfs -t ${ebs_master_fstype} ${ebs_master_dev} >/dev/null 2>&1"
yes | mkfs -t ${ebs_master_fstype} ${ebs_master_dev} >/dev/null 2>&1
sync
echo
# mount ...
[ -z "${ebs_master_mnt}" ] && { echo "please set ebs_master_mnt"; exit 1; }
[ -d "${ebs_master_mnt}" ] || mkdir ${ebs_master_mnt}
mount ${ebs_master_dev} ${ebs_master_mnt} >/dev/null 2>&1
mount | grep ${ebs_master_dev}
df ${ebs_master_dev} >/dev/null 2>&1 || { echo "not available: ${ebs_master_dev}"; exit 1; }
echo
# done
exit 0
▼wakame-ebs-mysql-master-delete-volume.sh
#!/bin/sh
#
# http://blog.hansode.org/
# 2009.05.12
#
##
## variables
##
# common
pwd=$(cd $(dirname $0) && pwd)
[ -f ${pwd}/_wakame-common.sh ] && . ${pwd}/_wakame-common.sh
##
## check phase
##
[ -b "${ebs_master_dev}" ] || { echo "not found: ${ebs_master_dev}"; exit 1; }
df ${ebs_master_dev} >/dev/null 2>&1 || { echo "not found: ${ebs_master_dev}"; exit 1; }
# ebs_master_volume=
ebs_master_volume=$(ec2-describe-volumes | grep ${ec2_instance_id} | grep ${ebs_master_dev} | grep attached | awk '{print $2}')
[ -z "${ebs_master_volume}" ] && { echo not found: ${ebs_master_dev}; exit 1; }
echo ${ebs_master_volume}
echo
# unmount...
echo "$ umount ${ebs_master_mnt}"
umount ${ebs_master_mnt}
for i in 1 2 3 4 5 6 7 8 9 10; do
echo -n ". "
sync
sleep 1
mount | grep ${ebs_master_dev} -q || break
done
echo
# detach volume...
echo "$ ec2-detach-volume ${ebs_master_volume}"
ec2-detach-volume ${ebs_master_volume}
for i in 1 2 3 4 5 6 7 8 9 10; do
echo -n ". "
sync
sleep 1
ec2-describe-volumes | grep ${ec2_instance_id} | grep ${ebs_master_dev} | grep attached -q || break
done
echo
# delete volume...
echo "$ ec2-delete-volume ${ebs_master_volume}"
ec2-delete-volume ${ebs_master_volume}
for i in 1 2 3 4 5 6 7 8 9 10; do
echo -n ". "
sync
sleep 1
ec2-describe-volumes | grep ${ec2_instance_id} | grep ${ebs_master_dev} | grep deleting -q || break
done
echo
# done
echo "$ ec2-describe-volumes"
ec2-describe-volumes
exit 0
スクリプトの準備
適当な作業ディレクトリを作成し、そのディレクトリにファイルを保存する。
# mkdir -p work/wakame # cd work/wakame
3つのスクリプトをそれぞれコピー&ペースト
# cat > _wakame-common.sh (コピー&ペースト) ^D # cat > wakame-ebs-mysql-master-create-volume.sh (コピー&ペースト) ^D # cat > wakame-ebs-mysql-master-delete-volume.sh (コピー&ペースト) ^D
実行可能状態にしておく
# chmod +x ./wakame-ebs-mysql-master-create-volume.sh # chmod +x ./wakame-ebs-mysql-master-delete-volume.sh
動作実行例
# ./wakame-ebs-mysql-master-create-volume.sh $ ec2-create-volume -z us-east-1b -s 1 ebs_master_volume:vol-d656b4bf $ ec2-attach-volume -d /dev/sdm -i i-f9047990 vol-d656b4bf ATTACHMENT vol-d656b4bf i-f9047990 /dev/sdm attaching 2009-05-14T05:11:46+0000 . . $ yes | mkfs -t ext3 /dev/sdm >/dev/null 2>&1
# ./wakame-ebs-mysql-master-delete-volume.sh vol-d656b4bf $ umount /home/wakame/mysql/data umount: /home/wakame/mysql/data is not mounted (according to mtab) . $ ec2-detach-volume vol-d656b4bf ATTACHMENT vol-d656b4bf i-f9047990 /dev/sdm detaching 2009-05-14T05:11:46+0000 . $ ec2-delete-volume vol-d656b4bf VOLUME vol-d656b4bf . $ ec2-describe-volumes VOLUME vol-d656b4bf 1 us-east-1b deleting 2009-05-14T05:11:38+0000
Amazon EBS Volumeの追加削除までが行える事を確認出来た。
Amazon EBSで困った事、気付いた事
いくつかハメられたポイントがあった
- 見た目はローカルデバイスである為、ネットワーク越しである事を忘れがち
- →その次の操作をして良い状態に遷移してない事が多い!!
確実性を持たせる為に、
- create直後にattachしない事
- attach直後にmkfsしない事
- detach直後にdeleteしない事
- →適度にsleepとsyncを入れ、Amazon EBS Volumeの状態が遷移した事を確認してから次の作業を行う事
これに気付くまでに、何度も同じ過ちを犯してしまった…。
スクリプト内にsleepとsyncが登場しているのは、これらを考慮している為だ。
次回は
MySQLのdatadirにAmazon EBS Volumeをマウントした設定。
- MySQL Master
- datadirにAmazon EBSを使う
- MySQL Masterのdatadirのsnapshot生成
- MySQL Slave
- 生成したsnapshotからMySQL Slave用のdatadirを作成
変更履歴
- 2009/05/15 16:30
- _wakame-common.shの内容修正
- ec2_local_ipv4を追加
- mysqld_master_info_hostの値を${ec2_local_ipv4}へ
オライリージャパン
売り上げランキング: 117000
2009年05月11日
ミッション: WakameにMySQL Slave自動追加機能を実装
自分がRubyを使い慣れてないので、手慣れているシェルスクリプトで動作を確認する。
動作確認後、Wakameコードに手を入れて行く。
まずは環境構築
必要な物は下記の通り。
EC2関連の利用までの手順は、今回省略する。
- Javaのランタイムパッケージ
- Amazon EC2 API Tools
- AWSの証明書(pk.pemとcert.pem)
ec2-api-toolsの環境設定
UbuntuであればJavaのランタイムパッケージをapt-getするだけ。
もしもUbuntu9.04以降であればec2-api-toolsもapt-getでインストール可能。
- パッケージインストール
- default-jre-handless
- ec2-api-tools
- 環境変数設定
- JAVA_HOME
- EC2_HOME
$ sudo apt-get install default-jre-headless $ export JAVA_HOME=/usr $ wget http://s3.amazonaws.com/ec2-downloads/ec2-api-tools-1.3-30349.zip $ unzip ec2-api-tools-1.3-30349.zip $ sudo mv -i ec2-api-tools-1.3-30349 /usr/local/ $ sudo ln -s /usr/local/ec2-api-tools-1.3-30349 /usr/local/ec2-api-tools $ export EC2_HOME=/usr/local $ /usr/local/ec2-api-tools/bin/ec2-version 1.3-30349 2008-12-01
次に、環境変数の設定。
pk.pemとcert.pemの保存先を指定する。
- 環境変数設定
- EC2_PRIVATE_KEY
- EC2_CERT
ダウンロード時のpk.pemとcert.pemのファイル名はもっと長い。
pk-********.pemとcert-********.pemと言ったファイル名だ。
今回は汎用性を持たせる為、pk.pemとcert.pemとした。
$ cd ~/ $ mkdir .ec2 $ chmod 700 .ec2 $ cd .ec2 $ cat > pk.pem 内容をコピー&ペースト ^D $ cat > cert.pem 内容をコピー&ペースト ^D $ export EC2_PRIVATE_KEY=$HOME/.ec2/pk.pem $ export EC2_CERT=$HOME/.ec2/cert.pem $ env | egrep ^EC2_ EC2_HOME=/usr/local/ec2-api-tools EC2_PRIVATE_KEY=/home/ubuntu/.ec2/pk.pem EC2_CERT=/home/ubuntu/.ec2/cert.pem
これで準備完了。
$ /usr/local/ec2-api-tools/bin/ec2-describe-instances RESERVATION r-4042d229 650811885664 wakame-default INSTANCE i-93ed9dfa ami-c25eb9ab ec2-75-101-199-66.compute-1.amazonaws.com domU-12-31-39-00-64-68.compute-1.internal running hansode0m1.small 2009-05-11T05:15:30+0000 us-east-1b aki-714daa18 ari-7e4daa17
動作確認としてec2-describe-instancesを実行。
Amazon EC2 API Toolsの動作を確認出来た。
次回は
今回は数多くblogで触れられている内容なので、面白く無い…
次回はMySQLのdatadirとして利用するAmazon EBS。
volumeの作成・削除をするシェルスクリプトを紹介予定。
オライリージャパン
売り上げランキング: 114475
2009年05月08日
手軽にスナップショット取得し、手軽にスレーブをセットアップしたい
複数のMySQL Slaveを作る際の手順が、どうも面倒臭い。
手軽に作成する方法を模索していたら、master.infoをあらかじめ作成する方法に辿り着いた。
- masterに「server-id」と「log_bin」の設定し、mysqld起動(または再起動)
- レプリケーション用MySQLアカウント作成
- masterのテーブルロック
- masterのデータ領域のスナップショット作成
- 「SHOW MASTER STATUS」を実行し、ログファイルとポジションをメモ
- slaveにスナップショットを伸長
- slaveに「server-id」の設定し、mysqld起動
- slaveにて「CHANGE MASTER TO」を実行すると、master.infoが生成される
- master.infoの情報を基に、レプリケーションが行われ、更新されて行く
- →だったら、master.infoを先に作っておいても良いんじゃないか?
master.infoを先に作る
先の手順でも触れた様に、「CHANGE MASTER TO」をすると、master.infoが生成される。
と言う事は、master.infoを作っておけば「CHANGE MASTER TO」を実行しなくて済むはずだ。
その仮説のもとに、master.infoをあらかじめ作ってみたら「CHANGE MASTER TO」を実行しなくても見事同期に成功した。
▼master.infoのフォーマットは下記ページより
http://dev.mysql.com/doc/refman/5.1/ja/slave-logs-status.html
| 行 | 説明 |
|---|---|
| 1: | ファイル内のライン番号 |
| 2: | マスタのバイナリログ名 |
| 3: | マスタのバイナリログ内の現在位置 |
| 4: | マスタのホスト名 |
| 5: | マスタに接続するためのユーザ名 |
| 6: | マスタに接続するためのパスワード |
| 7: | マスタに接続するためのネットワークポート |
| 8: | インターバル時間(秒) |
| 9: | サーバがSSL接続をサポートするかどうかを示す |
| 10: | 証明機関(CA)に使用したファイル |
| 11: | 証明機関(CA)へのパス |
| 12: | SSL証明書のファイル名 |
| 13: | SSL節夫z国使用している暗号法名 |
| 14: | SSLキーファイル名 |
▼サンプルmaster.info
1: 14 2: mysql-bin.000002 3: 98 4: 192.0.2.10 5: repl 6: password 7: 3306 8: 60 9: 0 10: 11: 12: 13: 14:
1行目は14で固定。
2行目〜7行目は「CHANGE MASTER TO」指定項目で見慣れたもの。
8行目〜14行目も固定。(SSL使用時は必要に応じて変更)
一撃スナップショット生成スクリプト「make-mysql-repl-snapshot.sh」
ここまでのスナップショット生成手順をまとめると、下記の通り。
- mysql> FLUSH TABLES WITH READ LOCK;
- datadir/master.infoを生成
- スナップショット作成
- mysql> UNLOCK TABLES;
- ※必要に応じてmaster.infoは削除。しなくても良い。
手順が分かればスクリプトを書ける。
一撃でスナップショットを生成するスクリプトを作成してみた。
#!/bin/sh
#
# http://blog.hansode.org/
#
export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin
# mysqld masterの管理項目
mysqld_master_dir=/var/lib/mysql # datadirのパス
mysqld_master_admin_host=127.0.0.1 # MySQL Masterのホスト名(or IPアドレス)
mysqld_master_admin_user=root # MySQL Masterの管理ユーザー名
# master.info生成用設定項目
mysqld_master_info_host=192.0.2.1 # Slaveから見たMasterのホスト名(or IPアドレス)
mysqld_master_info_user=repl # レプリケーション用ユーザー名
mysqld_master_info_pass=password # レプリケーション用パスワード
mysqld_master_info_port=3306 # Slaveから見たMasterのポート番号
# この例では、ホスト名とユーザー名の指定のみ行っている
# 必要に応じて -p などを追加して下さい
mysql_command() {
cat | mysql \
-h${mysqld_master_admin_host} \
-u${mysqld_master_admin_user} \
-s
# -p${mysqld_master_admin_pass} \
# -P${mysqld_master_admin_port} \
}
# connect test
echo "SHOW MASTER STATUS" | mysql_command >/dev/null || {exit 1;}
#
echo "... flush tables with read lock;";
echo "FLUSH TABLES WITH READ LOCK;" | mysql_command
#
echo "... show master status;";
mysqld_master_status=$(echo "SHOW MASTER STATUS;" | mysql_command)
set ${mysqld_master_status}
mysqld_master_binlog_file=$1
mysqld_master_binlog_pos=$2
#
echo "... make master.info"
cat <<EOS > ${mysqld_master_dir}/master.info
14
${mysqld_master_binlog_file}
${mysqld_master_binlog_pos}
${mysqld_master_info_host}
${mysqld_master_info_user}
${mysqld_master_info_pass}
${mysqld_master_info_port}
60
0
EOS
#
chmod 0644 ${mysqld_master_dir}/master.info
chown mysql:mysql ${mysqld_master_dir}/master.info
#
snapshot_id=$(date +%Y%m%d%H%M%S)
snapshot_file=/tmp/mysqld-${snapshot_id}.tar.gz
echo "... make snapshot: ${snapshot_file}"
cd ${mysqld_master_dir}/../
tar zcpf ${snapshot_file} $(basename ${mysqld_master_dir})
#
echo "... unlock tables;";
echo "UNLOCK TABLES;" | mysql_command
#
rm -f ${mysqld_master_dir}/master.info
exit 0
実行例
$ ./make-mysql-repl-snapshot.sh ... flush tables with read lock; ... show master status; ... make master.info ... make snapshot: /tmp/mysqld-20090508081942.tar.gz ... unlock tables;
あとはスナップショットをSalveのdatadirに伸長するだけ。
作業まとめ
master$ sudo vi /etc/my.cnf + [mysqld] + server-id = 1 + log_bin master$ sudo /etc/init.d/mysql restart master$ ./make-mysql-repl-snapshot.sh master$ scp /tmp/mysqld-%Y%m%d%H%M%S.tar.gz slave:/tmp/
slave$ sudo vi /etc/my.cnf + [mysqld] + server-id = 2 slave$ sudo /etc/init.d/msyql stop slave$ cd /var/lib slave$ sudo mv -i mysql _mysql slave$ sudo tar zxvpf /tmp/mysqld-%Y%m%d%H%M%S.tar.gz slave$ sudo /etc/init.d/msyql start
大分簡略化されたけど、これでもまだ手順が多い。
master.info生成法は「簡易量産型」
2台以上のスレーブを作成する時、特に重宝する。
master.info生成法のメリットをまとめてみると、
- スナップショットをdatadirに伸長した後、mysqldを起動するだけでslaveになる
- master.info生成時に「SHOW MASTER STATUS」の情報を一度メモするだけで良い
- slave設定時に「CHANGE MASTER TO」を実行せずに済む
Wakameに組み込む為の検証
今回の内容はWakameに組み込む為の検証の1つ。
次回はAmazon EC2/S3/EBSを使ったレプリケーション設定をご紹介予定。
オライリージャパン
売り上げランキング: 63543
Pragma
売り上げランキング: 27866
2008年11月03日
2008/10/30〜2008/10/31 東京
今回は二日目だけ参加。
二日目はチューニングに関するセッションが2つ。
とても奇麗なビル。
東京駅と直結しているので便利だ。
受付と、受付付近。
去年はまだSunに買収されてなかった。
今年はSun。お金のかけかたが違う。
受付は綺麗どころが揃っていた。
受付付近では各セッションの状況が中継されている。
事前登録者優先で席が決まる。
登録してない人はキャンセル待ち。
会場整理専門の人が誘導。
去年は居なかったなぁ。
去年はランチまでもが無料だった。
今年はランチ無し。残念。
去年同様、同時通訳してくれるのが他カンファレンスとは違う。
プレゼント抽選会。
今年も何も当たらなかった…
クジ運ないな。
受付横に巨大なMySQLイルカ
懇親会
MySQLエンジニアも参加。
こう言うことでもない限り知り合うきっかけがない。
何名かと名刺交換。
あっという間に食料が無くなった。
まとめ
- 今回、凄く良かったと思ったのはGURU BAR
- GURU BARとは、MySQLエンジニアが直接質問に答えてくれる場
- 恐らく普段なら有料なのだろう
- ここぞとばかりに質問して来た
ぜひ、また来年も参加したい。
2008年07月19日
Oreilly & Associates Inc
売り上げランキング: 3436
Amazonさんから届いた。
- MySQL 5.1対応
- ページ数は初版の2倍強
- 管理者だけでなく開発者向けの内容
この本でしばらく楽しめそうだ。
この夏、オススメの1冊。
2008年06月29日
2008/06/27(金) 恵比寿
前回に続き、今回も最前席。
気になった箇所だけツマミ食い。
- 設定を間違えるとパフォーマンス低下に繋がるケース
- show statusの結果と内容、その意味。
- ばらつきの少ないインデックスは無意味の可能性あり。
例:性別(男,女)。ばらついているからこそインデックスの意味がある - SELECT STARAIGHT_JOIN * from tbl1, tbl2...。
SQL文にかかれたテーブル順に処理を行う - SHOW [FULL] PROCESSLIST。
FULLが無い場合は出力が10バイト以内となる。
オライリージャパン
売り上げランキング: 47782
もう一度読み直して理解度増加。
2008/10/30と2008/10/31、
『MySQL User Conference Japan 2008』が開催されるとの事。
これは行くしかない。
変更履歴
- 2008/06/30 11:13
- MySQL Users Conference 2008の開催期間修正
× 2008/10/30と2008/10/30
○ 2008/10/30と2008/10/31
2008年06月14日
2008/06/13(金) 恵比寿
一番前の席。
満席だった。
各種ストレージエンジンの紹介。
今までストレージエンジンの使い分けを意識した事が無かった。
そんな自分には大変興味深い内容だった。
個人的に使ってみたくなったストレージエンジン
- Archive
- INSERTとSELECTのみ
- MyISAMと比べるとINSERTが1.5倍速い
- 変更しないデータ、ログ等向け
- データを圧縮して格納(70%〜80%)
- Blackhole
- Slave台数が多い場合に使う
- 多段のSlaveがある場合に効果を発揮
- 中間に位置するSlaveでBlackhole設定
- この時、バイナリログさえあればよい。
- SQL処理が不要となるのでIO負荷軽減となる
- Merge
- 複数テーブルを1つに見せる
- 例えば月別のログテーブルをMergeで1つに見せる
- 実態は複数
Falcon
- なるべくキャッシュ(メモリ)を使う
- rollbackはInnoDBよりも数倍速い
- 外部キーは対応しない
- 今後ストレージエンジンでは外部キーを実装しない方向性
- MySQLサーバ側で外部キーを扱うらしい
- よって、そのうち外部キーを使えるようになるはず
次回も参加したい
第4回 6月27日(金)15:00-17:00
「MySQLパフォーマンスチューニング」
MySQLのパフォーマンス監視のツボ
面白そうだ。
オライリージャパン
売り上げランキング: 11671




