はじめに
ローカルマシンでMaster-Slave構成のDBへのアクセステストを行うために、とりあえずで構築してみました。
MySQLは良く見かけるので、あえてMariaDBで。galera使って、MultiMaster構成も捨てがたかったけど、実案件でまだ使うことはなさそうなので、古き良きMaster-Slave構成を選択しました。
なお、同一サーバ上で複数のインスタンスを起動するために、mysqld_multiコマンドを使用しています。
使ったものは以下の通りです。
名前 | バージョン |
---|---|
Ubuntu | 16.04.2 |
MariaDB | 10.2.12 |
手順
なお、以後、シェル中のsudoは省略しています。
まずはリポジトリ
MariaDB公式サイトに従い、リポジトリを追加します。
# apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
# vi /etc/apt/sources.list.d/mariadb.list (以下記述)
deb [arch=amd64,i386] http://ftp.yz.yamagata-u.ac.jp/pub/dbms/mariadb/repo/10.2/ubuntu xenial main
deb-src http://ftp.yz.yamagata-u.ac.jp/pub/dbms/mariadb/repo/10.2/ubuntu xenial main
# apt-get update
そして、インストール
リポジトリからmariadb-serverをインストールします。
# apt-get install mariadb-server
余分なユーザーやテーブルを削除した後、一旦、サーバを止めます。
# mysql_secure_installation
# service mysql stop
スレーブ用インスタンスの作成
スレーブ用のデータディレクトリを作成し、データの初期設定を行います。
# mkdir /var/lib/mysql-slave
# chown mysql:mysql /var/lib/mysql-slave
# mysql_install_db --datadir=/var/lib/mysql-slave
二つのインスタンスを立ち上げる
my.cnfを複数インスタンス用に変更します。
# cp /etc/mysql/my.cnf /etc/mysql/my.cnf.orig
# vi /etc/mysql/my.cnf (下記の内容を追加)
(追加部分)
[mysqld_multi]
user = root
password = hogehoge
mysqld = /usr/bin/mysqld_safe
mysqladmin = /usr/bin/mysqladmin
[mysqld1]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
datadir = /var/lib/mysql
general_log_file = /var/log/mysql/mysql.log
general_log = 1
server-id = 1
report_host = master1
log_bin = /var/log/mysql/mariadb-bin
log_bin_index = /var/log/mysql/mariadb-bin.index
expire_logs_days = 3
max_binlog_size = 100M
[mysqld2]
pid-file = /var/run/mysqld/mysqld-slave.pid
socket = /var/run/mysqld/mysqld-slave.sock
port = 3307
datadir = /var/lib/mysql-slave
general_log_file = /var/log/mysql/mysql-slave.log
general_log = 1
server-id = 2
report_host = slave1
# slaves
relay_log = /var/log/mysql/relay-bin
relay_log_index = /var/log/mysql/relay-bin.index
relay_log_info_file = /var/log/mysql/relay-bin.info
read_only
mysqld1は、最初にインストールされたインスタンスでマスター部分になります。binary logを有効にし、server-idを指定しています。
mysqld2が、手動で追加したインスタンスでスレーブ部分になります。mysqld1の内容をコピーしてきて、PID、ソケット、データディレクトリなどをスレーブ用に変更しました。また、ポートを3307にしています。さらに、今回はrelay logを有効にし、read_onlyにしています。
では、mysqld_multiを使って、二つのインスタンスが立ち上がるか確認してみます(なお、この時点では二つのインスタンスはmaster-slaveの関係になっていません)。
# mysqld_multi start
# mysqld_multi report (確認用)
Reporting MariaDB servers
MariaDB server from group: mysqld1 is running
MariaDB server from group: mysqld2 is running
マスターとスレーブ
それでは、マスターからスレーブにデータをコピーし、同期を行うことにします。
マスター側
まず、マスター側サーバで、レプリケーション用のユーザを作成し、また、binary logの状態を記録しておきます。
# mysql -u root -P 3306 -h 127.0.0.1
> grant replication slave on *.* to repl@127.0.0.1 identified by 'REPLのパスワード';
> flush tables with read lock;
> show master status; (FileとPositionを記録しておく)
+--------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+--------------------+----------+--------------+------------------+
| mariadb-bin.000012 | 663 | | |
+--------------------+----------+--------------+------------------+
つづいて、マスター側のデータをダンプします。
# mysqldump -u root -p --all-databases --lock-all-tables -P 3306 -h 127.0.0.1 > /tmp/dbdump.db
さきほどread lockをかけていたので、忘れずにlockを解除しておきます。
# mysql -u root -P 3306 -h 127.0.0.1
> unlock tables;
スレーブ側
続いて、スレーブ側にマスターの設定を行い、スレーブを開始します。
問題なければ、show slave statusでパラメータが表示されるはずです。
# mysql -u root -P 3307 -h 127.0.0.1 < /tmp/dbdump.db
> change master to master_host='127.0.0.1', master_port=3306, master_user='repl', master_password='REPLのパスワード', master_log_file='記録したbinary logのファイル名', master_log_pos=記録したbinary logのPosition;
> start slave
> show slave status\G (確認用)
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 127.0.0.1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000012
Read_Master_Log_Pos: 663
Relay_Log_File: relay-bin.000018
Relay_Log_Pos: 964
(略)
ユーザと作業用databaseの作成
スレーブ側インスタンスにはread_onlyを付けていますが、このままでは、最初に作られた万能ユーザしか居ませんので、書き込みし放題です。
作業用データベースと、作業用ユーザを作成します。
データベース名や、作業用ユーザのIDやパスワードは適宜書き換えてください。(まさかデータベース用アカウントにSCOTT/TIGERを使っている人はいませんよね・・・)。
# mysql -u root -P 3306 -h 127.0.0.1
> create database workdb;
> create user scott@'127.0.0.1' identified by 'tiger';
> grant all on workdb.* to scott@'127.0.0.1';
スタートアップ
さて、このままでは、init.dには従来のmysqlが登録されたままになっているため、サーバを再起動したときに、マスター側のインスタンスしか立ち上がらないということになります。
mysqld_multi用のスクリプトを作成し、それと置き換えることにします。
# update-rc.d mysql remove
# cp /etc/init.d/mysql /etc/init.d/mysql_multi
# vi /etc/init.d/mysql_multi (以下のスクリプトを作成)
mysqld_multiの内容 (ひどい手抜き)
#!/bin/bash
#
### BEGIN INIT INFO
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Should-Start: $network $named $time
# Should-Stop: $network $named $time
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
### END INIT INFO
#
set -e
set -u
${DEBIAN_SCRIPT_DEBUG:+ set -v -x}
test -x /usr/sbin/mysqld || exit 0
. /lib/lsb/init-functions
SELF=$(cd $(dirname $0); pwd -P)/$(basename $0)
if [ -f /etc/default/mysql ]; then
. /etc/default/mysql
fi
# Safeguard (relative paths, core dumps..)
cd /
umask 077
case "${1:-''}" in
'start')
/usr/bin/mysqld_multi start
;;
'stop')
/usr/bin/mysqld_multi stop
;;
'restart')
$SELF stop
$SELF start
;;
*)
echo "Usage: $SELF start|stop|restart"
exit 1
;;
esac
スクリプトを登録します。
# update-rc.d mysql_multi defaults
# update-rc.d mysql_multi enable
これで、サーバの起動と終了がserviceコマンドで行えるようになるはず・・・
# service mysql_multi start
# mysqld_multi report
Reporting MariaDB servers
MariaDB server from group: mysqld1 is running
MariaDB server from group: mysqld2 is running
次に停止の確認。
# service mysql_multi stop
# mysqld_multi report
Wide character in print at /usr/bin/mysqld_multi line 599.
Reporting MariaDB servers
MariaDB server from group: mysqld1 is not running
MariaDB server from group: mysqld2 is running
あ、あれ・・・。
To-Do: 原因が分かったら記事を修正する。
(未完)
logrotate(追記)
このままでは、logrotateがマスター側のログのみを対象にしてしまうので、スレーブ側のログも対象にする。
# vi /etc/logrotate.d/mysql-server
下の行に、mysql-slave.logを追加します。
/var/log/mysql/mysql.log /var/log/mysql/mysql-slow.log /var/log/mysql/mariadb-slow.log /var/log/mysql/error.log
↓
/var/log/mysql/mysql.log /var/log/mysql/mysql-slow.log /var/log/mysql/mariadb-slow.log /var/log/mysql/error.log /var/log/mysql/mysql-slave.log
あと、ログがうまく書き込まれないケースがあるようなので、maskを640から660に変更しておきます。(調べてない)
create 640 mysql adm
↓
create 660 mysql adm
character-set(追記)
デフォルトだとcharacter-setがlatin1なので、utf8mb4に変更します。
my.cnfにcharacter-setを追記します。
(追加部分のみ)
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld1]
character-set-server = utf8mb4
[mysqld2]
character-set-server = utf8mb4