分布式扩展中最常用的一种模式就是主从复制,主从复制的主要作用是通过读写分离提高数据库的并发性能。复制指将主数据库的DDL(data definition language)和 DML(Data Manipulation Language) 操作通过二进制日志(bin log)传到从库服务器中,然后在从库上对这些日志重新执行,从而使得从库和主库的数据保持同步。Mysql支持一台主库同时向多台从库进行复制, 从库同时也可以作为其他从服务器的主库,实现链状复制。
Mysql默认使用异步复制
主从复制的原理如下所示,假设此时为单主单从模式

如上图所示
由于主从复制依赖于二进制日志文件(binlog),而binlog有三种格式
因此,主从复制也就有三种方式:
主从复制的优势主要包含如下几点:
主从ok的情况:在从库写入,不能写入主库
主库挂掉,随便写个从库,数据不能同步
异步复制是一个主库,一个或多个从库,数据异步同步到从库
这种模式下,主节点不会主动推送数据到从节点,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理
这种模式下,如果主节点崩溃,此时主节点上已经提交的事务可能并没有传到从节点上,此时会将从节点提升为主节点,可能导致新主节点上的数据不完整
Mysql默认使用的是异步复制,由于异步操作所带来的延迟,当主库由于某种原因导致binlog日志的丢失,没有成功的同步到从库上,那么就会造成主从之间的不一致性。
原因为:异步复制中,主库在执行完对binlog的commit操作后即可返回客户端,无需等待binlog日志成功的传送到从库上

而半同步复制执行时,为了保证主库中的binlog能够被可靠的复制到从库上,主库在每次成功提交事务后,并不是立即返回给客户端,而是等待binlog至少在一个从库上成功提交并写入到relaylog中。只有binlog成功的写入到了其中的一个从库中,主库才会给客户端反馈
一致性的保证:
relay log成功保存了日志,主库才会给客户端反馈bin log日志注意
- 主库和从库都要启用半同步复制才会进行半同步复制功能,否则主库会还原为默认的异步复制
- 当主库等待超时时,也会还原为默认的异步复制。当至少有一个从库赶上时,主库会恢复到半同步复制
开启并行复制后,会启动多个 Worker 线程,原有的 SQL 线程变为 Coordinator 线程。
可以并行的事务分发给 Worker 线程执行; 不能并行的事务等待 Worker 线程全部结束后,再由 Coordinator 线程自己执行。
DDL 语句或者是跨 Schema 的语句不能并行执行。
这种并行复制的模式,对于多个 DB 同时更新才能有较高的并行度,但是更常见的情况是更新集中在同个一个 DB。
一个简单的改进,把 Schema 级别的并行复制改成 Table 级别,可以大幅度提高单库多表环境下的并行度。但是对于只有一个热点表的情况依然处理不了。
相比 DATABASE 极大提高了并行度。
Group Commit 实现了主库事务的并行提交。很显然的,主库能同时进入prepare阶段的事务之间不会冲突,那么这些事务在备库回放时也不会冲突。
Group Commit 中,last_commited 相同的事务,可以在备库并行回放。
MySQL bin log 里面维护了两个变量
Logical_clock max_committed_transaction:记录上次 Group commit 时最大的 sequence_number,即上述 mysqlbinlog 中的 last_committed
Logical_clock transaction_counter:sequence_number 来源,每次分配 sequence_number 时 transaction_counter 进行递增,即当前最大的 sequence_number
5.7 的并行复制还有一点点弊端,如果如果主库并行度低,那么备库回放时也很难并行。
为此,5.7 引入了两个参数:
为了提高备库回放的速度,需要在主库尽量提高并行度。
8.0解决了这个问题,即使主库在串行提交的事务,只有互相不冲突,在备库就可以并行回放。
8.0 引入了参数 binlog_transaction_dependency_tracking 来控制事务依赖模式,让备库根据 commit timestamps 或者 write sets 并行回放事务,有三个取值:
WRITESET 是一个 hash 数组,大小由参数 binlog_transaction_dependency_history_size 决定。
参数 transaction_write_set_extraction 决定 hash 算法,可选值:OFF、MURMUR32、XXHASH64,默认值 XXHASH64,如果
WriteSet 记录了事务的更新行信息,决定 commit_parent时,使用事务自己的 session WriteSet 和 history WriteSet 进行比对,找到最近的冲突行,设为 commit_parent。如果 WriteSet 找不到 commit_parent,则还是使用 COMMIT_ORDERE 决定 commit_parent
在 MySQL 8.0 版本中,提供了多源复制,多源复制的出现对于分库分表的业务提供了极大的便利,
多源复制的好处
可以集中备份,在从库上备份,不会影响线上的数据正常运行
节约购买从库服务器的成本,只需要一个从库服务器即可
数据汇总在一起,方便后期做数据统计
减轻DBA维护工作量。