1. MysqlReplication同步原理
Mysql的 Replication 是一个异步的复制过程,从一个Mysql instace(我们称之为 Master)复制到另一个 Mysql instance(我们称之 Slave)。在 Master 与 Slave 之间的实现整个复制过程主要由三个线程来完成,其中两个线程(Sql线程和IO线程)在 Slave 端,另外一个线程(IO线程)在 Master 端。
要实现 MySQL 的 Replication ,首先必须打开 Master 端的BinaryLog(mysql-bin.xxxxxx)功能,否则无法实现。因为整个复制过程实际上就是Slave从Master端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。打开 MySQL 的 Binary Log 可以通过在启动 MySQLServer 的过程中使用 “—log-bin” 参数选项,或者在 my.cnf 配置文件中的 mysqld 参数组([mysqld]标识后的参数部分)增加 “log-bin” 参数项。
MySQL复制的基本过程如下:
1.Slave 上面的IO线程连接上 Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
2.Master 接收到来自 Slave 的 IO 线程的请求后,通过负责复制的 IO 线程根据请求信息读取指定日志指定位置之后的日志信息,返回给 Slave 端的 IO 线程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息在 Master 端的 Binary Log 文件的名称以及在 Binary Log 中的位置;
3.Slave 的 IO 线程接收到信息后,将接收到的日志内容依次写入到 Slave 端的Relay Log文件(mysql-relay-bin.xxxxxx)的最末端,并将读取到的Master端的bin-log的文件名和位置记录到master- info文件中,以便在下一次读取的时候能够清楚的高速Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”
4.Slave 的 SQL 线程检测到 Relay Log 中新增加了内容后,会马上解析该Log 文件中的内容成为在 Master 端真实执行时候的那些可执行的 Query 语句,并在自身执行这些Query。这样,实际上就是在 Master 端和 Slave 端执行了同样的 Query,所以两端的数据是完全一样的。
实际上,在老版本中,MySQL 的复制实现在 Slave 端并不是由 SQL 线程和 IO 线程这两个线程共同协作而完成的,而是由单独的一个线程来完成所有的工作。但是 MySQL 的工程师们很快发现,这样做存在很大的风险和性能问题,主要如下:
首先,如果通过一个单一的线程来独立实现这个工作的话,就使复制 Master 端的,Binary Log日志,以及解析这些日志,然后再在自身执行的这个过程成为一个串行的过程,性能自然会受到较大的限制,这种架构下的 Replication 的延迟自然就比较长了。
其次,Slave 端的这个复制线程从 Master 端获取 Binary Log 过来之后,需要接着解析这些内容,还原成 Master 端所执行的原始 Query,然后在自身执行。在这个过程中,Master端很可能又已经产生了大量的变化并生成了大量的Binary Log 信息。如果在这个阶段 Master 端的存储系统出现了无法修复的故障,那么在这个阶段所产生的所有变更都将永远的丢失,无法再找回来。这种潜在风险在Slave 端压力比较大的时候尤其突出,因为如果 Slave压力比较大,解析日志以及应用这些日志所花费的时间自然就会更长一些,可能丢失的数据也就会更多。
所以,在后期的改造中,新版本的 MySQL 为了尽量减小这个风险,并提高复制的性能,将 Slave 端的复制改为两个线程来完成,也就是前面所提到的 SQL 线程和 IO 线程。最早提出这个改进方案的是Yahoo!的一位工程师“Jeremy Zawodny”。通过这样的改造,这样既在很大程度上解决了性能问题,缩短了异步的延时时间,同时也减少了潜在的数据丢失量。
当然,即使是换成了现在这样两个线程来协作处理之后,同样也还是存在 Slave 数据延时以及数据丢失的可能性的,毕竟这个复制是异步的。只要数据的更改不是在一个事务中,这些问题都是存在的。
如果要完全避免这些问题,就只能用 MySQL 的 Cluster 来解决了。不过 MySQL的 Cluster 仍然还是一个内存数据库的解决方案,也就是需要将所有数据包括索引全部都 Load 到内存中,这样就对内存的要求就非常大的大,对于一般的大众化应用来说可实施性并不是太大。当然,在之前与 MySQL 的 CTO David 交流的时候得知,MySQL 现在正在不断改进其 Cluster 的实现,其中非常大的一个改动就是允许数据不用全部 Load 到内存中,而仅仅只是索引全部 Load 到内存中,我想信在完成该项改造之后的 MySQL Cluster 将会更加受人欢迎,可实施性也会更大。
Replication原理来看,可以有这些推论:
* 主从间的数据库不是实时同步,就算网络连接正常,也存在瞬间,主从数据不一致。
* 如果主从的网络断开,从会在网络正常后,批量同步。
* 如果对从进行修改数据,那么很可能从在执行主的bin-log时出现错误而停止同步,这个是很危险的操作。所以一般情况下,非常小心的修改从上的数据。
* 一个衍生的配置是双主,互为主从配置,只要双方的修改不冲突,可以工作良好。
* 如果需要多主的话,可以用环形配置,这样任意一个节点的修改都可以同步到所有节点。
2. Mysql主从同步配置
分别登录master机和slave机的mysql:mysql –u root –p
创建数据库:create database repl;
1、设置同步master
编辑配置文件 /etc/my.cnf 确保有如下行
server-id=1
binlog-do-db=repl //需要备份的数据库名,如果需要备份多个数据库,重复设置这个选项即可。
log-bin=mysql-bin //启动二进制日志系统
以下的几个参数可以不加:
log-err=my-err.log
log-bin=mysql-bin //启动二进制日志系统
binlog-ignore-db=mysql //不需要备份的数据库名,防止备份出错,可以把不备份的数据库写入这个参数中
log-slave-updates //这个参数是把更新的记录写到二进制文件中
slave-skip-errors //跳过错误,继续执行复制操作
创建一个mysql的账号为同步专用
mysql –u root –p
mysql> grant replication slave on *.* to 'gl'@'192.168.10.Slave' identifiedby '123456';
#grant replication slave on *.* to ‘用户名’@'主机’ identified by ‘密码’;
mysql> flush privileges; #刷新权限
重启master mysql
查看master状态
mysql>show master status;
查看进程:
mysql> show processlist;
3、设置同步slave
编辑配置文件
server-id=2
master-user=gl //同步账号
master-host=192.168.10.master //同步masterIP
master-password=123456 //同步密码
master-connect-retry=60 //心跳时间(库同步间隔)
master-port=3306 //master数据库的端口
replicate-do-db=repl //同步的数据库名
然后重启slave mysql
在slave机中进入mysql
mysql>start slave;
mysql>show slave status\G;
如果Slave_IO_Running、Slave_SQL_Running状态为Yes则表明设置成功。
查看slave状态
mysql>show master status;
查看进程:
mysql> show processlist;
3. Mysql双主同步
配置双向同步方法就是在单向同步的基础上略加改动,即在从机上做主机配置,在主机上做从机配置
注:mysql不支持多主的同步
4. MariaDB的多主一丛
目前MySQL依然只支持一个Slave从一个Master复制数据,虽然也可以做到一主多备(M->S),双主复制(M<->M)等架构,但是局限性依然很大。
MariaDB主从配置部分和mysql的配置方式无异,省略…。在此基础上,mariadb10以上版本开始支持多主的设置,如下:
change master 'r1' to master_host='192.168.200.51',master_user='rep',master_password='rep123456',master_log_file='mysql-bin51.000013',master_log_pos=107;
change master 'r2' tomaster_host='192.168.200.52',master_user='rep',master_password='rep123456',master_log_file='mysql-bin_52.000106',master_log_pos=107;
//其他参数同mysql
MariaDB的change方法和MySQL有点不一样,多了一个 ['connection_name'] ,这个就是多主一从的关键。为每个主设置一个通道标识,这样就可以支持多主复制了。
如何保存复制的信息?单主复制会把复制信息保存在master.info中,在多主复制中的保存也类似,只是在最后加上通道标识名称。如:
-rw-rw---- 1 mysqlmysql 11311月 17 10:30master-r1.info
-rw-rw---- 1 mysqlmysql 11411月 17 10:31master-r2.info
-rw-rw---- 1 mysqlmysql 24811月 17 10:30mysqld-relay-bin-r1.000001
-rw-rw---- 1 mysql mysql 29 11月 17 10:30mysqld-relay-bin-r1.index
-rw-rw---- 1 mysqlmysql 24811月 17 10:31mysqld-relay-bin-r2.000001
-rw-rw---- 1 mysqlmysql 2911月 17 10:31mysqld-relay-bin-r2.index
-rw-rw---- 1 mysqlmysql 5411月 17 10:30relay-log-r1.info
-rw-rw---- 1 mysql mysql 55 11月 17 10:31 relay-log-r2.info
#查看所有通道
MariaDB [(none)]>show all slaves status\G;
#查看单个通道
MariaDB [(none)]> show slave 'r1' status\G;
MariaDB [(none)]> show slave 'r2' status\G;
开启同步:
#开启单个通道 MariaDB [(none)]> start slave 'r1';
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> start slave 'r2';
Query OK, 0 rows affected (0.00 sec)
#关闭多个通道
MariaDB [(none)]> start all slaves;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
MariaDB [(none)]> show warnings;
+-------+------+--------------------+
| Level | Code | Message |
+-------+------+--------------------+
| Note | 1937 | SLAVE 'r2' started |
| Note | 1937 | SLAVE 'r1' started |
+-------+------+--------------------+
2 rows in set (0.00 sec)
#单个通道初始化
MariaDB [r1]> reset slave 'r1' all;
关闭同步:
#关闭单个通道 MariaDB [(none)]> stop slave 'r1';
Query OK, 0 rows affected (0.14 sec)
MariaDB [(none)]> stop slave 'r2';
Query OK, 0 rows affected (0.03 sec)
#关闭所有通道
MariaDB [(none)]> stop all slaves;
Query OK, 0 rows affected, 2 warnings (0.08 sec)
MariaDB [(none)]> show warnings;
+-------+------+--------------------+
| Level | Code | Message |
+-------+------+--------------------+
| Note | 1938 | SLAVE 'r2' stopped |
| Note | 1938 | SLAVE 'r1' stopped |
+-------+------+--------------------+
2 rows in set (0.00 sec)
多源复制在原先复制的基础上多了几个变量,现在来说明下:
5. 存在的问题
5.1. 此方案多作为机房内多个主机同步的解决方案
5.2. 避免同步发生错误的问题
mysql跳过大量replication错误的几种方法
http://blog.sina.com.cn/s/blog_53b13d9501015t8n.html
http://blog.itpub.net/26855487/viewspace-775827/
5.3. 同步过程中会发生各种停止同步、延时问题
MySQL Replication同步复制的延时监控
http://blog.csdn.net/kronus/article/details/7346248
http://www.cnblogs.com/blueel/archive/2013/01/06/2847842.html
relayfetch解决mysql replication主从延迟(另一种方案)
http://www.2cto.com/database/201306/220925.html
深入解析MySQL replication协议
http://www.open-open.com/lib/view/open1430795191241.html
mysql ReplicationDriver可以在jdbc层进行读写分离,主写从读
http://www.cnblogs.com/taven/archive/2013/04/24/3040489.html
http://blog.csdn.net/ckcs49/article/details/2064248
http://www.l99.com/EditText_view.action?textId=383249