目录
MySQL主从复制
主从复制时的日志格式:
复制架构:
1、一主多从架构
2、多级复制架构
3、双主复制/Dual Master架构
复制方式
一、异步复制
二、半同步复制
原理:将主服务器的binlog日志复制到从服务器上执行一遍,达到主从数据的一致状态。
过程:从库开启一个I/O线程,向主库请求Binlog日志。主节点开启一个binlog dump线程,检查自己的二进制日志,并发送给从节点;从库将接收到的数据保存到中继日志(Relay log)中,另外开启一个SQL线程,把Relay中的操作在自身机器上执行一遍
优点:
扩展:
这里的日志格式就是指二进制日志的三种格式:基于语句statement的复制、基于行row的复制、基于语句和行(mix)的复制。其中基于row的复制方式更能保证主从库数据的一致性,但日志量较大,在设置时考虑磁盘的空间问题
show variables like ‘%binlog%format%’; #查看当前使用的binlog的格式
set binlog_format = ‘row’; #设置格式,这种方法只在当前session生效
set global binlog_format = ‘row’; #在全局下设置binlog格式,会影响所有的Session
在主库的请求压力非常大时,可通过配置一主多从复制架构实现读写分离,把大量对实时性要求不是很高的请求通过负载均衡分发到多个从库上去读取数据,降低主库的读取压力。而且在主库出现宕机时,可将一个从库切换为主库继续提供服务
因为每个从库在主库上都会有一个独立的Binlog Dump线程来推送binlog日志,所以随着从库数量的增加,主库的IO压力和网络压力也会随之增加,这时,多级复制架构应运而生。
多级复制架构只是在一主多从的基础上,再主库和各个从库之间增加了一个二级主库Master2,这个二级主库仅仅用来将一级主库推送给它的BInlog日志再推送给各个从库,以此来减轻一级主库的推送压力。
但它的缺点就是Binlog日志要经过两次复制才能到达从库,增加了复制的延时。
我们可以通过在二级从库上应用Blackhol存储引擎(黑洞引擎)来解决这一问题,降低多级复制的延时。
“黑洞引擎”就是写入Blackhole表中数据并不会写到磁盘上,所以这个Blackhole表永远是个空表,对数据的插入/更新/删除操作仅在Binlog中记录,并复制到从库中去。
双主复制架构适用于需要进行主从切换的场景
在只有一个主库的架构下,当主库宕机后,将其中一个从库切换为主库继续提供服务。原来的主库就没有数据来源了,那么当这个新的主库接收到新的数据时,原来的主库却没有同步,因此他们的数据差异越来越大,那么原来的主库就无法成为主从复制环境中的一员了。当原来的主库恢复正常后,需要重新将其添加进复制环境中去。
那为了避免重复添加主库的问题,双主复制应运而生。两个数据库互为主从,当主库宕机恢复后,由于它还是原来从库(现在主库)的从机,所以它还是会复制新的主库上的数据。那么无论主库的角色怎么切换,原来的主库都不会脱离复制环境。
MySQL的主从复制有两种复制方式,分别是异步复制和半同步复制
配置:
前提:主从数据库的版本一致
主库:
1、在主库上设置一个用于复制的账号,并赋予replication slave权限
>grant replication slave on *.* to 'test'@'192.168.142.176' identified by '123';
>flush privileges;
2、开启主库的Binlog,并设置server-id
vim /mysql/3306/my.cnf
[mysqld]
log-bin = mysql-bin
server-id = 1
3、在主库上设置读锁定有效,目的是确保在此过程中没有对数据的操作,避免主从数据不一致
> flush tables with read lock;
4、获取主库上当前Binlog的日志名和偏移量,为了在从库中,从此位置开始复制
>show master status;
5、备份主库的数据
我这里的主从库是在一台服务器上,如果不在一台机器上,先将主库数据打包,到后面再传过去就可以了。这里我将主库的数据备份到了/test目录下(其实可以不用备份,后面直接cp到从库,但还是感受一下备份的安全感吧)
cp /mysql/3306/data /test
6、恢复主库的写操作
> unlock tables;
从库:
7、将第5步中备份的主库数据拷贝到从库上
cp /test /mysql/3307/data
8、从库配置文件中增加server-id,注意这个值是唯一的,要区别于主库和其他从库
vim /mysql/3307/my.cnf
[mysqld]
server-id = 2
9、启动从库
启动从库的时候,我们加一个--skip-slave-start参数,表示这个从库启动是不自动同步,也就是不启动主从复制进程,方便后面对从库的进一步配置
/usr/local/mysql/bin/mysqld_safe --defaults-file=/mysql/3308/my.cnf --skip-slave-start
注意:由于我这里用的是MySQL的多实例,所以启动的时候需要用--defaults-file参数指定一下具体实例的my.cnf文件,如果主从库不再同一台机器上,就不需要加这个参数了,默认是/etc/my.cnf
10、从库设置主从信息
> change master to
-> master_host='192.168.142.176', #主库服务器的IP
-> master_port=3306, #主库端口
-> master_user='test', #主库用于复制的用户
-> master_password='123', #用户密码
-> master_log_file='mysql-bin.000002', #主库的Binlog日志名
-> master_log_pos=570; #Binlog日志的偏移量(从什么位置开始复制)
这里的配置要参照之前在主库的配置
11、从库启动slave线程,并检查
>start slave;
>show processlist \G
如下图:
12、测试主从复制
主库上创建一张表,并加入数据,看从库是否复制
主:
>use test
>create table emp (id int,name varchar(11));
>insert into emp values(1,’tom’),(2,’jerry’);
然后在从库上查看:
>use test
>show tables;
>select * from emp;
可以看到,已经成功复制过去了
13、排错
如果在从库发现没有复制过来数据,先看看slave的状态
>show slave status \G
上图中,前面几行是主库的信息,红色框内的两个参数必须要是yes,才能正确复制
Slave_IO_Running表示从库的IO线程,Slave_SQL_running表示从库的SQL线程,两个必须都为yes。
如果为no,可以去从库的错误日志(log-err)中查看原因
到这里,MySQL的异步复制就配置完成了~
在异步复制中,主库执行完操作后,写入binlog日志后,就返回客户端,这一动作就结束了,并不会验证从库有没有收到,完不完整,所以这样可能会造成数据的不一致。
说到底,复制过程中数据是否一致,主要取决于Binlog日志的安全性与完整性
在MySQL中,有sync_binlog=n这一参数,他的值表示每进行n次事务提交,MySQL就将Binlog刷新到磁盘。如果这个值为1,就代表每提交一次事务(SQL),就将Binlog往磁盘刷新一次,这样一来,就算数据库宕机了,那么最多只能损失一次事务的数据。
但是,一旦多个事务并发提交时,由于受sync_binlog的限制,MySQL只能按顺序来处理这些请求,另外,高频率的刷新binlog对IO的影响也很大,进一步影响了数据库的性能,所以,一般这个值都设为0或者其他值,在数据的安全性和高并发下的性能之间取得一个平衡。
为了更加有效的保护Binlog的安全性和完整性,MySQL5 .5之后引入了半同步复制
在异步复制中,我们遇到的一个主要问题就是,在复制过程当中,主库不会去验证Binlog有没有成功复制到从库,那如果主库提交一个事务并写入Binlog中后,当从库还没有从主库得到Binlog时,主库宕机了或因磁盘损坏等故障导致该事务的Binlog丢失了,那从库就不会得到这个事务,也就造成了主从数据的不一致。
而半同步复制,当主库每提交一个事务后,不会立即返回,而是等待其中一个从库接收到Binlog并成功写入Relay-log中才返回客户端,所以这样就保证了一个事务至少有两份日志,一份保存在主库的Binlog,另一份保存在其中一个从库的Relay-log中,从而保证了数据的安全性和一致性。
另外,在半同步复制时,如果主库的一个事务提交成功了,在推送到从库的过程当中,从库宕机了或网络故障,导致从库并没有接收到这个事务的Binlog,此时主库会等待一段时间(这个时间由rpl_semi_sync_master_timeout的毫秒数决定),如果这个时间过后还无法推送到从库,那MySQL会自动从半同步复制切换为异步复制,当从库恢复正常连接到主库后,主库又会自动切换回半同步复制。
半同步复制的“半”体现在,虽然主从库的Binlog是同步的,但主库不会等待从库执行完Relay-log后才返回,而是确认从库接收到Binlog,达到主从Binlog同步的目的后就返回了,所以从库的数据对于主库来说还是有延时的,这个延时就是从库执行Relay-log的时间。所以只能称为半同步。
配置半同步复制:
半同步模式是作为MySQL5.5的一个插件来实现的,主从库使用的插件不一样
1、先确认MySQL服务器是否支持动态增加插件
mysql>select @@have_dynamic_loading
2、分别在主从库上安装对用插件
插件一般默认在MySQL安装目录/lib/plugin下,可以去查看一下是否存在
主库的插件是semisync_master.so,从库是semisync_slave.so
mysql>install plugin rpl_semi_sync_master soname ‘semisync_master.so’;
mysql>install plugin rpl_semi_sync_slave soname ‘semisync_slave.so’;
3、安装完成后,在plugin表(系统表)中查看一下
mysql>select * from mysql.plugin;
4、在主从库中开启半同步复制
主:
mysql>set global rpl_semi_sync_master_enabled=1;
mysql>set global rpl_semi_sync_master_timeout=30000;
从:
mysql>set global rpl_semi_sync_slave_enabled=1;
注意:如果之前配置的是异步复制,在这里要重启一下从库的IO线程,如果是全新的半同步则不用重启.
重启命令是:mysql>stop slave io_thread;start slave io_thread;
5、在主库上查看半同步复制的状态
mysql>show status like '%semi_sync';
在输出信息中,我们重点关注三个参数:
rpl_semi_sync_master_status OFF/ON #ON表示半同步复制打开,OFF表示关闭
rpl_semi_sync_master_yes_tx [number] #这个数字表示主库当前有几个事务说通过半同步复制到从库的
rpl_semi_sync_master_no_tx [number] #表示有几个事务不是通过半同步复制到从库的
如有错误,敬请指正~~