MySQL

2011年11月04日

[RHEL][ucarp][mysql] Linux+ucarpで作るMySQL冗長化構成

このエントリーをはてなブックマークに追加

環境構築する為の準備運動

ここ数日のエントリは、本エントリの環境を構築する為の検証作業。

準備運動が終わったので、いよいよ結合する時が来た。 この構成で環境構築する事が本エントリの主目的であって、信頼性を問うのは議論の対象外である。

検証環境
  • 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で良い
前提条件
作業概要
  1. ucarpの設定ファイルを作成
  2. upscript, downscriptを配置
  3. ucarpを起動
  4. サービスの状態を確認
環境定義
用途IPアドレスnfsディレクトリNICucarp状態
nfsクライアント192.0.2.12/24export: /var/lib/mysql/eth0master
nfsサーバ192.0.2.13/24mount: /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を使えば簡単に冗長化させる事が可能だ。


Linuxで作るアドバンストシステム構築ガイド (18Network Server Construction Guide)
デージーネット
秀和システム
売り上げランキング: 190665



半袖 at 18:30|PermalinkComments(0)TrackBack(0)

[RHEL][Linux][NFS][MySQL] mysql datadir on nfs

このエントリーをはてなブックマークに追加

信頼性はどうであれ、共有ディスクを使った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を起動
作業概要
  1. nfsサーバ
    1. /var/lib/mysql を公開領域として設定
  2. nfsクライアント, mysqld
    1. nfsサーバの/var/lib/mysqlを、自身の/var/lib/mysqlにnfsマウント
    2. 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を無効化か


Linuxで作るアドバンストシステム構築ガイド (18Network Server Construction Guide)
デージーネット
秀和システム
売り上げランキング: 190665



半袖 at 16:00|PermalinkComments(0)TrackBack(1)

2009年05月15日

[Wakame] Amazon EC2 API Toolsを使ってMySQL Slaveを作る (3/n)

このエントリーをはてなブックマークに追加

[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
  • MySQL Slave
    • slave用my.cnfが存在する
      • datadir = /home/wakame/mysql/data-slave/
      • server-id = 2

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に組み込む為の手順の確認で作り始めたスクリプト。
このスクリプト単体でも意外と便利なのでアウトプットしてみた。
1人でも良いので、誰かの役に立てればアウトプットした意味がある。

AWS(Amazon Web Service)を使うと、いろいろな事が簡単に出来る事を実感した。
今回の様に、一度スクリプトを作ってしまえば、その後の作業は物凄く単純化される。
AWSに惚れ直した。

今後、色々なデベロッパーによって面白い使い方がされて行くだろう。
その面白い使い方の1つが「Wakame」になるはずだ!




詳解 シェルスクリプト
アーノルド ロビンス ネルソン・H.F. ベーブ
オライリージャパン
売り上げランキング: 137177
実践ハイパフォーマンスMySQL
ジェレミ・D. ザウドニ デレク・J. ベリング
オライリージャパン
売り上げランキング: 101715
High Performance MySQL 2e
High Performance MySQL 2e
posted with amazlet at 09.05.15
A Lentz
Pragma
売り上げランキング: 6573



半袖 at 20:00|PermalinkComments(0)TrackBack(1)

2009年05月14日

[Wakame] Amazon EC2 API Toolsを使ってMySQL Slaveを作る (2/n)

このエントリーをはてなブックマークに追加

[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をマウントした設定。

  1. MySQL Master
    • datadirにAmazon EBSを使う
    • MySQL Masterのdatadirのsnapshot生成
  2. MySQL Slave
    • 生成したsnapshotからMySQL Slave用のdatadirを作成

変更履歴

2009/05/15 16:30
_wakame-common.shの内容修正
  • ec2_local_ipv4を追加
  • mysqld_master_info_hostの値を${ec2_local_ipv4}へ



詳解 シェルスクリプト
アーノルド ロビンス ネルソン・H.F. ベーブ
オライリージャパン
売り上げランキング: 117000



半袖 at 16:10|PermalinkComments(0)TrackBack(1)

2009年05月11日

[Wakame] Amazon EC2 API Toolsを使ってMySQL Slaveを作る (1/n)

このエントリーをはてなブックマークに追加

ミッション: 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の作成・削除をするシェルスクリプトを紹介予定。




詳解 シェルスクリプト
アーノルド ロビンス ネルソン・H.F. ベーブ
オライリージャパン
売り上げランキング: 114475



半袖 at 18:05|PermalinkComments(0)TrackBack(2)

2009年05月08日

[Wakame] 一味違ったMySQLレプリケーション設定「CHANGE MASTER TOをせず、あらかじめmaster.infoを作っておく」

このエントリーをはてなブックマークに追加

手軽にスナップショット取得し、手軽にスレーブをセットアップしたい

複数のMySQL Slaveを作る際の手順が、どうも面倒臭い。
手軽に作成する方法を模索していたら、master.infoをあらかじめ作成する方法に辿り着いた。

  1. masterに「server-id」と「log_bin」の設定し、mysqld起動(または再起動)
  2. レプリケーション用MySQLアカウント作成
  3. masterのテーブルロック
  4. masterのデータ領域のスナップショット作成
  5. 「SHOW MASTER STATUS」を実行し、ログファイルとポジションをメモ
  6. slaveにスナップショットを伸長
  7. slaveに「server-id」の設定し、mysqld起動
  8. slaveにて「CHANGE MASTER TO」を実行すると、master.infoが生成される
  9. master.infoの情報を基に、レプリケーションが行われ、更新されて行く
  10. →だったら、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」

ここまでのスナップショット生成手順をまとめると、下記の通り。

  1. mysql> FLUSH TABLES WITH READ LOCK;
  2. datadir/master.infoを生成
  3. スナップショット作成
  4. mysql> UNLOCK TABLES;
  5. ※必要に応じて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を使ったレプリケーション設定をご紹介予定。




実践ハイパフォーマンスMySQL
ジェレミ・D. ザウドニ デレク・J. ベリング
オライリージャパン
売り上げランキング: 63543
High Performance MySQL 2e
High Performance MySQL 2e
posted with amazlet at 09.05.08
A Lentz
Pragma
売り上げランキング: 27866



半袖 at 18:50|PermalinkComments(0)TrackBack(0)

2008年11月03日

「MySQL ユーザコンファレンス2008」へ行って来た

このエントリーをはてなブックマークに追加

2008/10/30〜2008/10/31 東京

MySQL ユーザコンファレンス 2008

今回は二日目だけ参加。
二日目はチューニングに関するセッションが2つ。

NEC_3693 NEC_3696

とても奇麗なビル。
東京駅と直結しているので便利だ。

NEC_3700 NEC_3699

受付と、受付付近。
去年はまだSunに買収されてなかった。
今年はSun。お金のかけかたが違う。
受付は綺麗どころが揃っていた。

NEC_3701

受付付近では各セッションの状況が中継されている。

NEC_3694

事前登録者優先で席が決まる。
登録してない人はキャンセル待ち。

会場整理専門の人が誘導。
去年は居なかったなぁ。

NEC_3695

去年はランチまでもが無料だった。
今年はランチ無し。残念。

NEC_3697 NEC_3698

去年同様、同時通訳してくれるのが他カンファレンスとは違う。

NEC_3702 NEC_3703

プレゼント抽選会。
今年も何も当たらなかった…
クジ運ないな。

NEC_3704

受付横に巨大なMySQLイルカ

NEC_3705 NEC_3706

懇親会
MySQLエンジニアも参加。
こう言うことでもない限り知り合うきっかけがない。
何名かと名刺交換。

NEC_3707 NEC_3708
NEC_3709

あっという間に食料が無くなった。



まとめ

  • 今回、凄く良かったと思ったのはGURU BAR
    • GURU BARとは、MySQLエンジニアが直接質問に答えてくれる場
    • 恐らく普段なら有料なのだろう
    • ここぞとばかりに質問して来た

ぜひ、また来年も参加したい。




半袖 at 01:25|PermalinkComments(2)TrackBack(0)

2008年07月19日

High Performance MySQL

このエントリーをはてなブックマークに追加

High Performance MySQL
High Performance MySQL
posted with amazlet at 08.07.19
Baron Schwartz Peter Zaitsev Vadim Tkachenko Jeremy D. Zawodny Arjen Lentz
Oreilly & Associates Inc
売り上げランキング: 3436

Amazonさんから届いた。
  • MySQL 5.1対応
  • ページ数は初版の2倍強
  • 管理者だけでなく開発者向けの内容
斜め読みしただけでも充実した内容である事が分かる。
この本でしばらく楽しめそうだ。

この夏、オススメの1冊。



半袖 at 16:10|PermalinkComments(2)TrackBack(0)

2008年06月29日

第4回MySQL ウィークリーセミナー「MySQLパフォーマンスチューニング」

このエントリーをはてなブックマークに追加

2008/06/27(金) 恵比寿


NEC_2995
Powered by PICS


前回に続き、今回も最前席。
気になった箇所だけツマミ食い。

  • 設定を間違えるとパフォーマンス低下に繋がるケース
  • show statusの結果と内容、その意味。
  • ばらつきの少ないインデックスは無意味の可能性あり。
    例:性別(男,女)。ばらついているからこそインデックスの意味がある
  • SELECT STARAIGHT_JOIN * from tbl1, tbl2...。
    SQL文にかかれたテーブル順に処理を行う
  • SHOW [FULL] PROCESSLIST。
    FULLが無い場合は出力が10バイト以内となる。

実践ハイパフォーマンスMySQL
ジェレミ・D. ザウドニ デレク・J. ベリング
オライリージャパン
売り上げランキング: 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



半袖 at 15:10|PermalinkComments(2)TrackBack(0)

2008年06月14日

第3回MySQL ウィークリーセミナー 「MySQL ストレージエンジン徹底比較」へ行って来た

このエントリーをはてなブックマークに追加

2008/06/13(金) 恵比寿


NEC_2872
Powered by PICS


一番前の席。
満席だった。

各種ストレージエンジンの紹介。

今までストレージエンジンの使い分けを意識した事が無かった。
そんな自分には大変興味深い内容だった。



個人的に使ってみたくなったストレージエンジン


  • 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のパフォーマンス監視のツボ

面白そうだ。


実践ハイパフォーマンスMySQL
ジェレミ・D. ザウドニ デレク・J. ベリング
オライリージャパン
売り上げランキング: 11671



半袖 at 14:00|PermalinkComments(2)TrackBack(0)