本部分主要以理论为主,具体的主从搭建环境,大家可以参考博客其他部分。下面我就给大家数说主从复制那些理论的东西。说的不一定都是正确的,有不同出入的地方,欢迎大家一起交流沟通,以下我把我自己整理出来的主从复制的一些理论部分。
复制的概念
MySQL复制就是一台MySQL服务器(slave)从另一台MySQL服务器(master)进行日志的复制然后再解析日志并应用到自身
复制的应用
第一:是解决宕机带来的数据不一致,因为MySQL复制可以实时备份数据;
第二:是减轻数据库服务器的压力,多台服务器的性能一般比单台要好。但是MySQL复制不适合大数据量,大数据量推荐使用集群。
复制的原理图:
replication涉及到的三个线程
1 master上的 binlog dump(dump线程),即读取master上的binlog,发送到slave上的线程。
2 slave上的IO线程:读取slave上的relay log。
3 slave上的sql线程:执行IO线程读取的relay log的线程。
复制相关的日志格式,提供3种格式:Row 格式(首先我们的推荐的)。mix 格式(5.7后版本把他忘记吧)statements 格式(传统的复制格式)
基于row 格式的一些优点:
优点: 1、相比statement更加的安全复制的格式
2、在某些情况下速度更快(SQL 复杂,表有主键)
3、系统特殊函数也可以复制
4、更少的锁
缺点: Binary log 比较大(mysql-5.6 支持binlog_row_image)
单语句更新[删除]表的行数过多,会形成大量的binlog
无法从binlog看见用户执行的SQL
基于语句 (statements )的复制优缺点:
优点:1.Binlog 文件比较小
2.日志包含了用户执行的原始的SQL,方便统计和审计
3.出现最早 binlog 兼容比较好
4 Binlog 方便阅读方便故障的修复。
缺点:1 存在安全的隐患 可能导致主从结构不一致
2 对一些系统函数不能准确的复制或是不能复制
不支持的一些复制函数LOAD_FILE() UUID(), UUID_SHORT(),USER(),FOUND_ROWS(),SYSDATE() (unless both the master and the slave are started with the --sysdate-is-now option),GET_LOCK(),IS_FREE_LOCK(),IS_USED_LOCK(),MASTER_POS_WAIT(),RAND(),RELEASE_LOCK(),SLEEP(),VERSION()
在主从复制的过程当中我们引入GTID的复制方式是首选。可以参考我博客里面关于GTID部分的内容。
小的提示:在使用ROW 格式中DDL 语句还会记录STATEMENT 格式。这个我们要注意一下。
三:复制的几种类型,异步复制 ,半同步复制, 增强半同步复制,同步复制。
异步复制(Asynchronous replication)
MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,
这样就会有一个问题,主如果crash掉了,
此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
全同步复制(Fully synchronous replication)
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
半同步复制(Semisynchronous replication)
介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。
设置半同步:
set rpl_semi_sync_master_wait_point=AFER_COMMIT
无损复制优于半同步复制的原因:
一个事务提交(commit)的过程时,在MySQL 层的write biblog 步骤后,master节点需要收到一个至少一个slave节点回复的ack(表示收到了binlog)后,才继续下一个事务;如果在一定时间内(timeout)内没有收到ack 则切换为异步模式,二进制日志(binlog) 先写远程(IO 线程接收到即可),可保证数据完全不丢失。
不丢失的半同步复制 原因是:Master 在收到salve 的ACK 应答后才Commit 事物,事物复制到slave前。并发的事物看不到当前的事物的数据当Master 故障时,所有已提交的事物都会复制到slave 上。
无损复制性能优于半同步复制的原因
1 就等待ACK 回包问题上,其实两种复制的开销是一样的,没有区别,都是网络的等待开销。
2 无损复制由于在write binlog(commit的第二步)后,需要等待ACK,后续的事务无法提交,这样就堆积了很多需要落盘的事务(半同步复制由于已经提交了事务,没有堆积事务的效果),通过组提交机制,一次fsync的事务变多了(半同步复制也有组提交,只是一次fsync的事务数没那么多),相当于提高了I/O 性能所以线程(事务)越多,效果越明显。
1 传统的复制:异步复制是不需要等待从服务器的任何的确认信息。
2:半同步复制:
半同步复制是异步复制的升级替代的方案,可以提高数据完整性,从服务器收到更新,或者超时返回返回客户端,中间有一个ack 确认的问题。
semi-sync replication(半同步复制):在一个事务提交的过程时,在InnoDB层的commit log步骤后,Master节点需要收到至少一个slave 节点回复的ACK (表示收到了binlog)后,
才能继续下一个事务。如果在一定时间内(timeout)内没有收到ACK,则切换为异步模式。
- 至少有一个slave 节点收到binlog 后在返回(IO 线程接收到即可)
- 减少数据丢失风险
- 不能完全避免数据丢失
- 超时后,切换回异步复制
控制 半同步复制 还是无损复制 的参数设置:
AFTER_SYNC 表示无损的复制(5.7 默认)
AFTER_COMMIT 表示的是半同步复制
rpl_semi_sync_master_wait_point=AFTER_SYNC
至少收到1个 slave发回的ack: rpl_semi_sync_master_wait_for_slave_count=1
小结:
事实上,半同步复制并不是严格意义上的半同步复制,当半同步复制发生超时时(由rpl_semi_sync_master_timeout参数控制,单位是毫秒,默认为10000,即10s),会暂时关闭半同步复制,转而使用异步复制。当master dump线程发送完一个事务的所有事件之后,如果在rpl_semi_sync_master_timeout内,收到了从库的响应,则主从又重新恢复为半同步复制
在一主多从的架构中,如果要开启半同步复制,并不要求所有的从都是半同步复制。
MySQL 5.7极大的提升了半同步复制的性能,独立出一个 ack collector thread ,专门用于接收slave 的反馈信息。
这样master 上有两个线程独立工作,可以同时发送binlog 到slave,和接收slave的反馈
低于5.7 的版本,在从库关闭一段时间后,刚启动时。注意先用异步复制,复制追上后,在用半同步复制
master:
set global rpl_semi_sync_master_enabled=ON|OFF;
slave:
set global rpl_semi_sync_slave_enabled=ON|OFF;
要想使用半同步复制,必须满足以下几个条件:
1. MySQL 5.5及以上版本
2. 变量have_dynamic_loading为YES
3. 异步复制已经存在
首先加载插件
因用户需执行INSTALL PLUGIN, SET GLOBAL, STOP SLAVE和START SLAVE操作,所以用户需有SUPER权限。
主:mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
从:mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
show plugins;查看插件是否安装成功
rpl_semi_sync_master | ACTIVE | REPLICATION | semisync_master.so | GPL
启动半同步复制
在安装完插件后,半同步复制默认是关闭的,这时需设置参数来开启半同步
主:mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
从:mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;
查看半同步是否在运行:这两个变量常用来监控主从是否运行在半同步复制模式下。
主:mysql> show status like 'Rpl_semi_sync_master_status';
从:mysql> show status like 'Rpl_semi_sync_slave_status';
四:半同步常见问题:
- 网络问题,切换到异步复制
- 从库网络,IO 问题导致主库性能下降
- 从库故障 利用备份还原后加入集群中,把主库拖跨
- 复制结构中可以让binlog 备份服务保持增强半同步,如果binlog 备份能如何保持半同步,整个结构安全度会增加很多,另外要考虑复制结构中单库的约束,整个实列的大小:单实例1T左右、SAS盘 Raid10 : 单实例500G以下、单库: 200G。
五:为了增强复制引入了并行复制的概念。
在Master并发commit 事物多时,slave上并发性能越好
为什么要引入多线程的复制,5.5 的 问题,延迟问题非常的严重,5.6 开始版本支持多线程复制,每一个库有一个独立SQL线程进行回放对于有多个库的实列有帮助,对于单实列的库依然是单线程。主从复制,多线程大大的增强了从库的能力, 5.7 版本支持多线程复制,保留基于库的多线程回放,保留基于库的多线程回放,增加根据组提交进行完全的并行复制模式,Enhanced multi-threaded slave.
小结:并发复制:MySQL5.6 的并发复制是基于库级别的,MySQL5.7 的并发复制是基于事物级别(logical Clock)
实质上需要:1 让在Master 上能并发执行的事物,在Slave上也并发执行。
2 在binlog 中记录事物并执行的相关信息
3 slave 上根据以上这些信息,让这些事物在slave 上多个线程中并发执行
并行复制微调参数
binlog_group_commit_sync_delay
binlog_group_commit_sync_no_delay_count
slave_preserve_commit_oder=ON|OFF
开启binlog,Logical_clock 有作用
GTID模式下启动并行复制:
stop slave sql_thread;
set global salve_parallel_workers=8;
set global slave_paralle_type="LOGICAL_CLOCK";# OR DATABASE
start slave sql_thread
小结:事物能不能并行是锁来决定的,如果有锁冲突,则一个事物要等待另外一个事物执行完毕
如何判断并行事物有没有锁的冲突?
如果有两个事物(操作) 可以并执行,这两个事物有没有锁的冲突。
当事物开始执行commmit 语句或者事务进入preare阶段时,它已经获取了所有的锁。
实时同步:PXC 、Group-Replication
Group Replication 实质是: 二进制日志: 基于row格式+ 全局事物标识,增强半同步 和并行复制的一个组合,可以理解成一个通信框架+事物排序控制。
五:为什么会出现复制延迟的问题?
原因是复制都是基于row+gtid这样的结构运行这样会出现复制的延迟,还有另外原因就是主库出或者从库异常掉电、磁盘写入超时,进程异常crash 或者进程被kill掉。
解决的办法:可以使用MySQL5.7+row+gtid+增强半同步
关于复制延迟问题:如果遇到从库延迟,怎么定位是一个大事务造成从库延迟,排查的方法怎么做?
show slave status\G; 查看一下我们复制的状态信息。
发现 exec_master_log_position参数一直卡着不动。这是在复制过程会开启2个线程IO 一个是我们的IO_thread,另外一个是SQL_Thread,
IO_thread:主要是去读取我们远程master dump 到slave 机器的 relay_log。
观察read_master_log_file==relay_master_log_file && read_master_log_pos = exec_master_log_pos(同样适合GTID)
如果我们的second_behind 的值是大于0的,second_behind_master = IO_Thread.timestamp -SQL_Thread.timestamp 这时候也说明有了延迟,但是等于0也不能说就没有延迟。这个值一般是不太准确的
自己要把握好。
复制我们需要关注的几个参数:
相关的参数 |
|
|
|
|
|
slave_IO_Running |
yes |
NO 需要关注 |
|
|
|
slave_SQL_Running |
yes |
NO 需要关注 |
|
|
|
seconds_behind_master |
0 |
大于0 需要关注 |
单纯这个值是不能判定延迟。需要结合其他参数一起看 |
|
|
last Errno & last Error |
0 |
|
|
|
|
六:什么时候需要去校验我们的数据?
- 主从结构其中某个节点异常的重启
- 复制出错,修复后需要安排校验
- 核心库或是核心,每个月为周期全部需要校验一次
- 业务级别校验:记账类业务,基于小时级别校验及每天的整体校验
- DBA 可以利用percona-tools去校验