レプリケーション動作原理
レプリケーションにおける考え方は「2 つのデータベースに含まれるデータが同じであり、それに対して加える変更も同じであれば結果も同じである」というもの。
マスターに対してどのような変更が加えられたかを連続的に記録し、同じ変更をスレーブに転送する。スレーブ上では、マスターから送られてきた変更履歴を連続的に再生する。そうすることで、スレーブのデータはマスターに追随することになる。
以上の仕組みを実現させるために、MySQL には以下の機能が実装されている。
- マスター上の変更を記録するためのバイナリログ
- スレーブへデータを転送するためのマスタースレッド
- スレーブ上でデータを受け取り、リレーログに記録するための IO スレッド
- リレーログからデータを読み取り、それを再生するための SQL スレッド
バイナリログ
バイナリログとは、MySQL サーバ上で発生した全ての変更を直列化し、記録するための仕組み。バイナリログは MySQL のデータディレクトリ上に作成され、log_bin オプションで指定したファイル名のプレフィクスに 6 桁の連番がついた名前のファイルとして格納される。
実際に /etc/my.cnf
にて log_bin オプションを指定すると、/var/lib/mysql/
配下にログが配置されることを確認できる。
$ cat /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mysqld according to the
# instructions in http://fedoraproject.org/wiki/Systemd
log_bin=mysql-bin
expire_logs_days = 7
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
$ ls -l /var/lib/mysql/mysql-bin.*
-rw-rw---- 1 mysql mysql 509 8月 6 04:51 /var/lib/mysql/mysql-bin.000001
-rw-rw---- 1 mysql mysql 19 8月 6 04:50 /var/lib/mysql/mysql-bin.index
上記の mysql-bin.index はバイナリログインデックスファイルであり、バイナリログのファイル名がリストアップされている。
$ sudo cat /var/lib/mysql/mysql-bin.index
./mysql-bin.000001
また、SHOW BINARY LOGS でも確認可能。
このコマンドはバイナリログインデックスファイル (mysql-bin.index) の中身を読み取り、且つ個々のバイナリログを日ありて、ファイルサイズを読み取って表示するというもの。
mysql> SHOW BINARY LOGS;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 509 |
+------------------+-----------+
1 row in set (0.00 sec)
上記はバイナリログの中身には一切関与しないため、中身を見るには SHOW BINLOG EVENTS コマンドを使うか、mysqlbinlog コマンドを利用する。
mysql> SHOW BINLOG EVENTS;
+------------------+-----+-------------+-----------+-------------+----------------------------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+-------------+-----------+-------------+----------------------------------------------------------------+
| mysql-bin.000001 | 4 | Format_desc | 1 | 107 | Server ver: 5.5.60-log, Binlog ver: 4 |
| mysql-bin.000001 | 107 | Query | 1 | 190 | create database hoge |
| mysql-bin.000001 | 190 | Query | 1 | 301 | use `hoge`; create table hogehoge (id int, name varchar(20)) |
| mysql-bin.000001 | 301 | Query | 1 | 369 | BEGIN |
| mysql-bin.000001 | 369 | Query | 1 | 482 | use `hoge`; insert into hogehoge (id, name) values (0, 'hoge') |
| mysql-bin.000001 | 482 | Xid | 1 | 509 | COMMIT /* xid=9 */ |
+------------------+-----+-------------+-----------+-------------+----------------------------------------------------------------+
6 rows in set (0.00 sec)
$ sudo mysqlbinlog /var/lib/mysql/mysql-bin.000001 | head -10
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#180806 4:50:35 server id 1 end_log_pos 107 Start: binlog v 4, server v 5.5.60-log created 180806 4:50:35 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG '
m9NnWw8BAAAAZwAAAGsAAAABAAQANS41LjYwLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
MySQL 5.0 までは、バイナリログは SQL 文そのものが記録されており、この方式をステートメントベースレプリケーション (SBR) と呼ぶ。
SBR には問題があり、UUID () 関数を使う場合など、結果がその都度ことなる SQL 文を発行する際にマスター - スレーブ間で整合性が崩れる点である。
このように実行するたびに結果が同じになることが保証されない SQL は非決定性 (Non-deterministic) であるといわれ、SBR にとっては天敵である。以下のようなものが該当する。
- 非決定性の UDF やストアドプログラムを含む SQL 文
- ORDER BY 句なしで LIMIT 句が適用された UPDATE / DELETE
-
次の関数を含む SQL 文
- LOAD_FILE()
- UUID() / UUID_SHORT()
- USER()
- FOUND_ROWS()
- SYSDATE()
- GET_LOCK()
- IS_FREE_LOCK()
- IS_USED_LOCK()
- MASTER_POS_WAIT()
- RAND()
- RELEASE_LOCK()
- SLEEP()
- VERSION()
このような非決定性の SQL に起因する問題を克服するため、MySQL 5.1 において、行ベースレプリケーション (RBR) というモードが追加された。
これは SQL を実行した結果、変更が生じた行の変更前と変更後の値を記録する方法である。行単位で記録するため、SBR よりもバイナリログのサイズが大きくなるものの、SQL が非決定性かどうか振り回される心配はない。
また、さらに Mixed ベースレプリケーション (MBR) も存在する。これは SBR と RBR を必要に応じて使い分ける、というものであり、非決定性 SQL が出た段階で RBR に自動で切り替わるものである。