[MySQL][MariaDB] 同じマシン内にDBレプリケーションのスレーブを構築するには

通常、DBのレプリケーションは異なるマシンで行うものですが、動作テストや別ディスクにバックアップする目的で同一マシンでレプリケーションを行うこともできます。
基本的な手順は [DBのレプリケーション構築手順](http://qiita.com/suzutsuki0220/items/e5be03ea8f44ad2f6533) と同じです

# 前提

以下の手順を進める前に、[DBのレプリケーション構築手順](http://qiita.com/suzutsuki0220/items/e5be03ea8f44ad2f6533)を参考にし、マスターのダンプを/tmp/dbdump.dbに書き出し、バイナリログのFileとPositionを確認しておいてください

# 準備

## スレーブDBのディレクトリを作成

<pre>
# mkdir /srv/flash/mysql-slave
# chown mysql.mysql /srv/flash/mysql-slave
</pre>

ここでは、/srv/flash/mysql-slave に作成しています。また、MySQLプロセスはmysqlユーザーで実行される事を想定しています。異なる場合は適宜読みかえてください

## スレーブ用のmy.cnfを作成

稼働中のマスターの設定ファイルをスレーブDB用にコピーします

<pre>
# cp /etc/my.cnf /srv/flash/mysql-slave
</pre>

## my.cnfの変更

* server-idを設定します
<pre>
server-id=2
</pre>
※server-id はレプリケーション内で被らないように割り当てて下さい
* スレーブではバイナリログは不要ですので、log-binの行をコメントアウトします
<pre>
#log-bin=mysql-bin
</pre>
* マスターと被らないように、待ち受けするポート番号とUNIXドメインのソケットファイルのパスを変更します
<pre>
port           = 3307
socket         = /srv/flash/mysql-slave/mysql.sock
</pre>

## 起動、停止スクリプトの作成

以下のようなスクリプトを用意します

```shell-session:mysql-slave.sh
#!/bin/sh
# Start/stop/restart mysqld.
#
# Copyright 2003  Patrick J. Volkerding, Concord, CA
# Copyright 2003  Slackware Linux, Inc., Concord, CA
# Copyright 2008, 2013  Patrick J. Volkerding, Sebeka, MN, USA
# Copyright 2015  suzutsuki0220 Japan
#
# This program comes with NO WARRANTY, to the extent permitted by law.
# You may redistribute copies of this program under the terms of the
# GNU General Public License.

# To start MariaDB automatically at boot, be sure this script is executable:
# chmod 755 /etc/rc.d/rc.mysqld

# Before you can run MariaDB, you must have a database.  To install an initial
# database, do this as root:
#
#   mysql_install_db --user=mysql
#
# Note that the mysql user must exist in /etc/passwd, and the created files
# will be owned by this dedicated user.  This is important, or else mysql
# (which runs as user "mysql") will not be able to write to the database
# later (this can be fixed with 'chown -R mysql.mysql /var/lib/mysql').
#
# To increase system security, consider using "mysql_secure_installation"
# as well.  For more information on this tool, please read:
#   man mysql_secure_installation

# To allow outside connections to the database comment out the next line.
# If you don't need incoming network connections, then leave the line
# uncommented to improve system security.
SKIP="--skip-networking"

# Uncomment the next line to use Oracle's InnoDB plugin instead of the included XtraDB
#INNODB="--ignore-builtin-innodb --plugin-load=innodb=ha_innodb.so"

# Uncomment the next line to use TokuDB
#TOKUDB="--plugin-load=ha_tokudb"

CONF_FILE="/srv/flash/mysql-slave/my.cnf"
PID_FILE="/srv/flash/mysql-slave/mysql-slave.pid"
DATA_DIR="/srv/flash/mysql-slave/data"

# Start mysqld:
mysqld_start() {
  if [ -x /usr/bin/mysqld_safe ]; then
    # If there is an old PID file (no mysqld running), clean it up:
    if [ -r ${PID_FILE} ]; then
#      if ! ps axc | grep mysqld 1> /dev/null 2> /dev/null ; then
      if ! grep "mysqld" /proc/`cat ${PID_FILE}`/cmdline 1> /dev/null 2> /dev/null ; then
        echo "Cleaning up old ${PID_FILE}."
        rm -f ${PID_FILE}
      fi
    fi

    if ! [ -z "$TOKUDB" ]; then
      echo "never" > /sys/kernel/mm/transparent_hugepage/enabled
      echo "never" > /sys/kernel/mm/transparent_hugepage/defrag
    fi

    /usr/bin/mysqld_safe --defaults-file=${CONF_FILE} --datadir=${DATA_DIR} --pid-file=${PID_FILE} $SKIP $INNODB $TOKUDB &
  fi
}

# Stop mysqld:
mysqld_stop() {
  # If there is no PID file, ignore this request...
  if [ -r ${PID_FILE} ]; then
    #killall mysqld
    kill `cat ${PID_FILE}`
    # Wait at least one minute for it to exit, as we don't know how big the DB is...
    for second in 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 \
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 60 ; do
      if [ ! -r ${PID_FILE} ]; then
        break;
      fi
      sleep 1
    done
    if [ "$second" = "60" ]; then
      echo "WARNING:  Gave up waiting for mysqld to exit!"
      sleep 15
    fi
    if ! [ -z "$TOKUDB" ]; then
        echo "always" > /sys/kernel/mm/transparent_hugepage/enabled
        echo "always" > /sys/kernel/mm/transparent_hugepage/defrag
    fi
  fi
}

# Restart mysqld:
mysqld_restart() {
  mysqld_stop
  mysqld_start
}

# Check process running
mysqld_status() {
  if [ -r ${PID_FILE} ]; then
    if grep "mysqld" /proc/`cat ${PID_FILE}`/cmdline 1> /dev/null 2> /dev/null ; then
      echo "process running - `cat ${PID_FILE}`"
    else
      echo "process down, but PID file exists"
    fi
  else
    echo "process down"
  fi
}

case "$1" in
'start')
  mysqld_start
  ;;
'stop')
  mysqld_stop
  ;;
'restart')
  mysqld_restart
  ;;
'status')
  mysqld_status
  ;;
*)
  echo "usage $0 start|stop|restart|status"
esac
```

Slackware Linuxのrcスクリプトから変更を加えた物です

CONF_FILE, PID_FILE, DATA_DIR のパラメータは適宜変更してください
また、バックアップ用のスレーブでは不要かと思いますが、ネットワーク経由からスレーブにアクセスできるようにするには、"SKIP="で始まる行をコメントアウトしてください

# スレーブの構築

## DBの復元

1. datadirとdefaults-fileのオプションを指定して mysql_install_db を実行します
<pre>
# mysql_install_db --user=mysql --datadir=/srv/flash/mysql-slave/data --defaults-file=/srv/flash/mysql-slave/my.cnf
</pre>
2. スレーブのMySQLを起動します
<pre>
# ./mysql-slave.sh start
</pre>
※ 準備の手順で作成したスクリプトから起動します
3. マスターで書き出したデーターを復元します
<pre>
# mysql --user=root --socket=/srv/flash/mysql-slave/mysql.sock < /tmp/dbdump.db
</pre>
4. rootのパスワードを変更します
<pre>
# mysqladmin -u root --socket=/srv/flash/mysql-slave/mysql.sock password 'root'
</pre>

## スレーブの設定

1. マスターのホスト、レプリケーションのユーザー、パスワード、マスターのダンプ手順で確認したバイナリログのFileとPositionを設定します
<pre>
# mysql --user=root --socket=/srv/flash/mysql-slave/mysql.sock -p
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.0.241',  MASTER_PORT=3306, MASTER_USER='repl', MASTER_PASSWORD='password', MASTER_LOG_FILE='mysql-bin.000183', MASTER_LOG_POS=32579;
Query OK, 0 rows affected (0.25 sec)
</pre>
2. スレーブをSTARTします
<pre>
MariaDB [(none)]> START SLAVE;
Query OK, 0 rows affected, 1 warning (0.01 sec)
</pre>

※ [DBのレプリケーション構築手順](http://qiita.com/suzutsuki0220/items/e5be03ea8f44ad2f6533) と同じです

# スレーブにクライアントから接続するには

mysqlコマンドで、ソケットファイルを指定します。

<pre>
$ mysql --user=root -p --socket=/srv/flash/mysql-slave/mysql.sock
</pre>