参考文献
主从复制:https://www.cnblogs.com/Aiapple/p/5792939.html
主从复制:https://www.jianshu.com/p/cfcd27a4a459
MySQL 官网主从复制:https://dev.mysql.com/doc/refman/5.7/en/replication.html
一 什么是主从复制?
简单说就是让一台 MySQL 服务器去复制另外一台 MySQL 的数据,使两个服务器的数据
保持一致。
二 主从复制的意义是啥?
1、MySQL 主从复制用途
- 实时灾备,故障切换。当主库发生故障时,可以快速切到某个从库提升为主库,因为正常情况下数据一样,不会影响系统运行。
- 架构扩展,读写分离。当 MySQL 主库服务器请求压力大时,将读请求流量切到各个从库,降低主库压力,形成读写分离架构。
2、主从部署必要条件
- 主库开启 binlog 日志
- 主从 server_id 不同
- 从库服务器能连通主库
- 主从版本一致
三 binlog 是什么?
MySQL 有两类日志,一类是 MySQL 服务器日志,一类是底层存储引擎日志,由于这两个
日志存在,MySQL 事务采用二阶段提交方式。
其中服务器日志就是 binlog,即二进制日志(binary log),是 MySQL 更改数据库操作日志,
在事务提交的时候,记录到 binlog 中,从库可以从主库获取 binlog 执行实现主从最终一致。
binlog 主要有三种录入格式,分别是 statement-based,row-based 和 mixed(混合型)。
a. statement-based
当使用 statement-based 方式,Master 将修改数据的 SQL 语句写入 binlog 中,slave 获取
binlog 文件后执行 SQL 语句持久化;
优点:
1)经过磨练的方式;
2)binlog 日志文件相对较小。当 update or delete 时,存入的是 SQL 语句,不是更新
或删除的逐行数据。日志文件小,从库获取 binlog I/O 读取效率高,同时使用 binlog 恢复
数据会更快。
3)binlog 含有所有的修改 SQL 语句,可以做 SQL 审计;
缺点:
有些 DML 语句操作不确定,不能使用 statement-based 方式记录。比如 UUID() ,
SYSDATE() 等,从库执行 binlog 时,跟主库的值不一致,导致主库和从库数据不一致。
可以参考官网记录,哪些不能使用 statement-based 记录格式。
b. row-based
当使用 row-based 方式,Master 会将表中每一行的修改记录写入到 binlog 文件中,
slave 获取 binlog 文件后逐行执行;
优点:
1)所有的改变都可以写入到日志,是最安全的方式;
2)对于任何 INSERT/UPDATE/DELETE操作,row-based 方式需要更少的行锁;
缺点:
1)记录更多的日志文件,同时 binlog 日志写入会被锁住,如果数据量太大,会导致性能问题;
2)日志量大,主从复制 I/O 慢,恢复数据,花费更多时间;
c. mixed
MySQL 可以混合使用 statement-based 和 row-based 两种方式(MIXED FORMAT),
在记录日志时,MySQL 会选择最合适的方式记录日志,
比如,alter table,采用 statement-based,update 采用 row-based,由具体的存储引擎
和执行语句决定。
d. binlog 开启查看
- show variables like '%log_bin%';(查看 binlog 是否开启)
- 在 MySQL 的 cnf 配置文件设置 log_bin 参数,设置 binlog 路径重启 MySQL 开启;
show variables like '%log_bin%';
log_bin:代表是否开启了 binlog,其默认值为 OFF
log_bin_basename:binlog 存储文件的完整名称,会在默认的文件名后面添加上递增的序号,
就例如 mysql-bin.000001
log_bin_index binlog:索引文件名称,例如 mysql-bin.index
sql_log_bin:在 binlog 开启的时候,可以禁用当前 session 的 binlog
e. binlog 格式查看
show variables like '%binlog%format%';
四 主从复制模型
- 一主一从
- 主主复制
- 一主多从(扩展系统读取的性能,因为是在从库读取)
- 多主一从(5.7开始支持)
- 级联复制
一主一从,一主多从
一个主库往一个或多个从库复制。比较简单,从库使用时需要控制好应用权限和场景。
比如一个从库用于业务读,一个用于办公网研发查询,一个用于数据统计等。
主主复制
主主复制是将两个主库数据相互复制,数据实时热备份,直接容灾切换,或进行负载均衡,
保证主库的高可用。
级联复制
主库复制压力比较大,减少 log dump 线程开销,按级联方式进行复制数据,容易主从数据
不一致概率较大。
多主一从
分散主库压力,最后数据都汇总到一个从库,进行数据统计。
五 主从复制原理
从库开启一个 I/O 线程(I/O thread),连接主库发送请求到主库(传 pos,binlog event等参数)
获取 binlog 日志。主库会创建一个 log dump 线程(dump thread),检查 binlog event,根据
从库要求,将 binlog 发送给从库 I/O 线程,从库 I/O 线程将 binlog 写入 relay log(中继日志)。
从库开启 SQL 线程(SQL thread),取 relay log 文件中的日志,并解析成具体操作执行,
实现主从数据最终一致性;
注意:
1)从库 SQL 线程执行完 relay log 中的事件后,会将当前的中继日志删除,避免占用磁盘空间;
2)为了保证从库重启后,仍然知道从哪里开始复制,从库默认会创建两个文件 master.info 和
relay-log.info,分别记录了从库 I/O 线程当前读取主库 binlog 的进度和 SQL 线程处理 relay log
的进度。可以通过 show slave status \G 命令查看从库当前复制的状态。
六 问题及解决方法
MySQL 主从复制存在的问题:
- 主库宕机后,数据可能丢失;
- 从库只有一个 SQL Thread,主库写压力大,复制很可能延时;
解决方法:
- 半同步复制(解决数据丢失的问题);
- 并行复制(解决从库复制延迟的问题);
七 主从复制方式
1、异步复制
异步复制是 MySQL 默认的方式。在异步复制下,主库不会主动的向从库发送 binlog,
而是等待从库的 I/O 线程建立连接,从库 I/O 线程请求主库二进制日志事件(传pos等),
然后主库创建 dump
线程,检查自己的 binlog event,将对应位置的 binlog 发送给从库
I/O 线程,从库 I/O 线程将接收到的 binlog 写入到 relay log(中继日志) 中,从库开启
SQL 线程从relay log 中刷入到从库磁盘,完成主从异步复制操作。
主库处理用户请求和主从复制是两个完全异步化的过程。
2、同步复制
同步模式则是,主库执行一个事务,那么主库必须等待所有的从库全部执行完事务返回 commit 之
后才能给客户端返回成功。
主库会直接提交事务,而不是等待所有从库返回之后再提交。MySQL 只是延迟了对客户端的
返回,并没有延后事务的提交。同步模式性能会大打折扣,它把客户端的请求和主从复制耦合
在了一起,如果有某个从库复制线程执行的慢,那么对客户端的响应也会慢很多。
3、半同步复制
半同步相对于同步的区别在于,同步复制需要等待所有的从库 commit,而半同步只需要一个
从库 commit 就可以返回了。如果超过默认的时间仍然没有从库 commit,就会切换为异步模式
再提交。客户端也不会一直去等待了。
因为即使后面主库宕机了,也能至少保证有一个从库节点是可以用的,此外还减少了同步时的
等待时间。
4、并行复制
MySQL 并行复制
- 社区版 5.6 中新增
- 并行是指从库 SQL 线程负责转发到多个 worker 线程去处理日志
- 库级别并行应用 binlog,同一个库数据更改还是串行的(5.7 版并行复制基于事务组),一个事务发送到一个 worker 线程执行
设置
set global slave_parallel_workers=10;
设置 sql 线程数为 10。
八 其他
部分数据复制
主库添加参数:
binlog_do_db=db1
binlog_ignore_db=db1
binlog_ignore_db=db2
或从库添加参数
replicate_do_db=db1
replicate_ignore_db=db1
replicate_do_table=db1.t1
replicate_wild_do_table=db%.%
replicate_wild_ignore_table=db1.%
联级复制(常用)
A->B->C
B 中添加参数:
log_slave_updates
B 将把 A 的 binlog 记录到自己的 binlog 日志中
复制的监控:
show slave status \G
复制出错处理
常见:1062(主键冲突),1032(记录不存在)
解决:
- 手动处理
- 跳过复制错误:set global sql_slave_skip_counter = 1
九 总结
1、主从模型
- 一主一从
- 一主多从--扩展系统读取性能
- 多主一从--5.7开始支持
- 主主复制
- 联级复制
联级复制(常用)
- A->B->C
- B 中添加参数 log_slave_updates
- B 将把 A 的 binlog 记录到自己的 binlog 日志中
2、主从复制用途
实时灾备的故障切换,读写分离。
3、主从复制原理
- 主:log dump 线程传 binlog;
- 从
I/O 线程接受读取 binlog,并写入 relay log 文件
SQL 线程从 relay log 文件中读取 binlog 并持久化
4、问题及解决
- 异步复制方式,当主库宕机后,数据丢失,可以采用半同步复制方式处理;
- 主库写压力大,因从库只有一个 SQL 线程来持久化,复制可能延迟,可以使用并行复制,多线程处理;
复制的监控
show slave status
复制出错处理
- 常见:1062(主键冲突),1032(记录不存在)
- 解决:
手动处理
跳过复制错误:set global sql_slave_skip_counter=1
5、复制方式
a. 主从异步复制
主库提交事务写完 binlog 直接返回客户端,无需关心从库是否复制成功。响应快,但是一单
主库故障,容易丢数据。
b. 主从同步复制
主库提交事务写完 binlog 需要等所有从库 commit 后才返回客户端,数据一致性有保证,
但是并发性能极低。
c. 主从半同步复制
主库提交事务写完 binlog 后需要从库返回一个已接受,才放回给客户端;在数据一致性和
并发性能之间的一种折中方式。
- 5.5 集成到 MySQL,以插件的形式存在,需要单独安装
- 确保事务提交后 binlog 至少传输到一个从库
- 不保证从库应用完成这个事务的 binlog
- 性能有一定的降低
- 网络异常或从库宕机,卡主库,直到超时或从库恢复
d、并行复制
从库正常只有一个 I/O Thread 和 SQL Thread 处理数据复制,主库数据量大后,从库复制不过
来,主从延迟。从库多线程 apply binlog,保证复制的速度。
- 在社区5.6中新增
- 库级别并行应用 binlog,同一个库数据更改还是串行的
- 5.7 版本并行复制基于事务组
6、主从复制注意事项
MySQL 主从复制是 MySQL 高可用性,高性能(负载均衡)的基础;
简单,灵活,部署方式多样,可以根据不同业务场景部署不同复制结构;
复制过程中应该时刻监控复制状态,复制出错或延时可能给系统造成影响;
MySQL 主从复制目前也存在一些问题,可以根据需要部署复制增强功能;