一、缘由
最近在研究MySQL的复制及各种高可用架构,发现基本都是基于主从复制的组合。而主从复制是基于binary log的,
故这里就详细介绍下基于binary log event(二进制日志事件)复制的原理。
主从复制有实现两种方法:传统复制方式(基于server_id)和GTID(全局事务ID)。(MySQL5.6以后支持)
二、原理详解
1.简单来说(三个线程三个步骤):
1)主服务器Master将数据库的改变写入二进制日志文件,并维护一个等待从服务器连接的线程binlog_dump;
2)从服务器Slave会启动一个线程(IO Thread)和主服务器Master的binlog_dump线程建立连接,然后将数据
读取到从服务器Slave,并写入中继日志(Relay log);
3)从服务器Slave另一个线程(SQL thread)会从中继日志中读取数据,并在从数据库应用更新,完成数据同步。
2.细节实现:
MySQL使用3个线程来执行复制功能(一个在主服务器,两个在从服务器)。
1)当从服务器发出start slave时,从服务器Slave创建一个I/0线程,去连接主服务器Master并让他发送记录在其二进制日志中的语句。
2)主服务器Master创建一个线程Binlog Dump将二进制日志中的内容发送到从服务器Slave。(可在show processlist中看到该线程)
3)从服务器Slave I/O线程读取主服务器Binlog Dump线程发送过来的内容并将数据拷贝到从服务器数据目录中的中继日志中Relay log。
4)从服务器Slave创建SQL线程,用于读取中继日志并执行日志中包含的更新。
在从服务器上读取和执行更新语句被分成两个独立的任务,当从服务器启动时,其I/O线程可以很快地从主服务器Master索取所有
二进制日志内容,同时交由SQL线程来更新应用到从库(会有点慢)。
3.复制线程的状态
通过show processlist可以看到三个线程的状态,show slave status 可以看到IO、SQL线程的状态。常见的状态有:
1)主服务器Binlog Dump线程状态:
Master has sent all binlog to slave; waiting for binlog to be updated
线程已经从二进制日志中读取所有主要的更新并已经发送到从服务器。
线程现在正空闲,等待由主服务器上新的更新导致的出现在二进制日志文件中新的事务。
2)从服务器I/O线程状态:
Waiting for master to send event
线程已经连接上主服务器,正在等待二进制日志事件到达。如果主服务器正空闲,会持续较长时间。
如果等待持续slave_net_timeout秒,则发生超时。此时,线程认为连接中断并企图重新连接。
3)从服务器SQL线程状态:
Reading event from the relay log
线程已经从中继日志中读取一个事件,可以对事件进行处理了。
Slave has read all relay log;waiting for the slave I/O thread to update it
线程已经处理了中继日志文件中的所有事件,现在正在等待I/O线程将新事件写入中继日志。
4.复制过程中状态的保持:
从服务器通过在my.cnf设置如下参数,将主从状态保存在mysql库的表中slave_master_info、slave_relay_log_info。
下次从服务器启动时,读取这个表来确定它已经从主服务器读取了多少二进制日志,已经自己处理装机日志的程度。
relay_log_info_repository = TABLE
master_info_repository = TABLE