MySQL的Replication(英文为复制)是一个多MySQL数据库做主从同步的方案,特点是异步复制,广泛用在各种对MySQL有更高性能、更高可靠性要求的场合。与之对应的是另一个同步技术是MySQL Cluster,但因为MySQL Cluster配置比较复杂,所以使用者较少。

MySQL的 Replication是一个异步复制的过程(mysql5.1.7以上版本分为异步复制和半同步两种模式),它是从一个Mysql instance(instance英文为实例)(我们称之为Master)复制到另一个Mysql instance(我们称之slave)。在master与slave之间实现整个复制过程主要由三个线程来完成,其中两个线程(SQL线程和IO线程) 在slave端,另外一个线程(IO线程)在master端。

要实现MySQL的 Replication,首先必须打开master端的binlog (mysql-bin.xxxxxx)日志功能,否则无法实现mysql的主从复制。因为mysql的整个主从复制过程实际上就是:slave端从 master端获取binlog日志,然后再在自己身上完全顺序的执行该日志中所记录的各种SQL操作。
如何开启mysql的binlog日志呢?
在my.inf主配置文件中直接添加三行

log_bin=ON  
log_bin_basename=/var/lib/mysql/mysql-bin  
log_bin_index=/var/lib/mysql/mysql-bin.index

三个参数来指定,
第一个参数是打开binlog日志
第二个参数是binlog日志的基本文件名,后面会追加标识来表示每一个文件
第三个参数指定的是binlog文件的索引文件,这个文件管理了所有的binlog文件的目录

当然也有一种简单的配置,一个参数就可以搞定

log-bin=/var/lib/mysql/mysql-bin

这一个参数的作用和上面三个的作用是相同的,mysql会根据这个配置自动设置log_bin为on状态,自动设置log_bin_index文件为你指定的文件名后跟.index

这些配置完毕之后对于5.7以下版本应该是可以了,但是我们这个时候用的如果是5.7及以上版本的话,重启mysql服务会报错。这个时候我们必须还要指定一个参数

server-id=123454

随机指定一个不能和其他集群中机器重名的字符串,如果只有一台机器,那就可以随便指定了

有了上述的配置之后,我们就可以重新启动我们的mysql了

service mysqld restart

启动成功之后,我们可以登陆查看我们的配置是否起作用

show variables like ‘%log_bin%’

java 实现主从同步 主从同步的原理_MySQL

下面我们可以找到这个目录来看一下

java 实现主从同步 主从同步的原理_java 实现主从同步_02


因为我这里已经操作过数据库了,所以能看到这里有多个mysql-bin的文件,还有一个mysql-bin.index的文件,我们可以打开这个文件来看一下

java 实现主从同步 主从同步的原理_数据库_03


到这里,我们的binlog日志就打开了。

java 实现主从同步 主从同步的原理_数据库_04

MySQL主从复制的基本交互过程
1、slave端的IO线程连接上master端,并请求从指定binlog日志文件的指定pos节点位置(或者从最开始的日志)开始复制之后的日志内容。

2、master端在接收到来自 slave端的IO线程请求后,通知负责复制进程的IO线程,根据slave端IO线程的请求信息,读取指定binlog日志指定pos节点位置之后的日 志信息,然后返回给slave端的IO线程。该返回信息中除了binlog日志所包含的信息之外,还包括本次返回的信息在master端的binlog文 件名以及在该binlog日志中的pos节点位置。

3、slave端的IO线程在接收 到master端IO返回的信息后,将接收到的binlog日志内容依次写入到slave端的relaylog文件(mysql-relay- bin.xxxxxx)的最末端,并将读取到的master端的binlog文件名和pos节点位置记录到master-info(该文件存在slave 端)文件中,以便在下一次读取的时候能够清楚的告诉master“我需要从哪个binlog文件的哪个pos节点位置开始,请把此节点以后的日志内容发给 我”。

4、slave端的SQL线程在检 测到relaylog文件中新增内容后,会马上解析该log文件中的内容。然后还原成在master端真实执行的那些SQL语句,并在自身按顺丰依次执行 这些SQL语句。这样,实际上就是在master端和slave端执行了同样的SQL语句,所以master端和slave端的数据是完全一样的。

以上mysql主从复制交互过程比较拗口,理解起来也比较麻烦,我简化了该交互过程。如下:

  1. 主库db的更新事件(update、insert、delete)被写到binlog
  2. 主库创建一个binlog dump thread,把binlog的内容发送到从库
  3. 从库启动并发起连接,连接到主库
  4. 从库启动之后,创建一个I/O线程,读取主库传过来的binlog内容并写入到relay log
  5. 从库启动之后,创建一个SQL线程,从relay log里面读取内容,从Exec_Master_Log_Pos位置开始执行读取到的更新事件,将更新内容写入到slave的db

从以上mysql的Replication原理可以看出:

  • 主从间的数据库不是实时同步,就算网络连接正常,也存在瞬间主从数据不一致的情况。
  • 如果主从的网络断开,则从库会在网络恢复正常后,批量进行同步。
  • 如果对从库进行修改数据,那么如果此时从库正在在执行主库的bin-log时,则会出现错误而停止同步,这个是很危险的操作。所以一般情况下,我们要非常小心的修改从库上的数据。
  • 一个衍生的配置是双主、互为主从配置,只要双方的修改不冲突,则可以工作良好。
  • 如果需要多主库的话,可以用环形配置,这样任意一个节点的修改都可以同步到所有节点