主从复制

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

Mysql默认使用异步复制

原理

主从复制的原理如下所示,假设此时为单主单从模式

mysql中ddl是什么 mysql ddl dml dcl_mysql中ddl是什么


如上图所示

  • 当master节点执行insert、update和delete等DML操作时,对应的语句会按序写入到bin log中
  • slave节点需要使用mater节点提供的账号和密码连接到mater节点,并且对每一个slave节点都创建一个binlog dump线程
  • 当master节点的binlog发生改变时,binlog dump线程会通知所有的slave节点,并将相应的binlog内容推送到slave节点
  • 当IO线程接受到binglog内容后,就将内容写入到slave节点本地的relay log中
  • SQL线程就会读取IO线程写入的relay log,并且根据relay log的内容对slave节点的数据库做相应的操作;操作执行成功后,relay log中的内容将会被删除

复制方式

由于主从复制依赖于二进制日志文件(binlog),而binlog有三种格式

  • Statement:基于SQL语句级别,记录每条修改数据的SQL语句
  • Row:基于行级别,记录每行数据的详细变化;一致性更好,但更大
  • Mixed:混合模式,默认使用Statement
开启二进制文件
  • log_bin=master-bin

因此,主从复制也就有三种方式:

• binlog_format=Statement:基于SQL语句的复制
• binlog_format=Row:基于行的复制
• binlog_format=Mixed:混合复制模式

优势

主从复制的优势主要包含如下几点:

  • 当master节点发生故障时,可以快速的切换到slave节点继续提供服务,保证数据库服务的可用性
  • 实现读写分离,降低mater节点的访问压力
  • 可以在slave节点中执行备份,以避免备份期间影响master节点的服务

劣势

主从ok的情况:在从库写入,不能写入主库

主库挂掉,随便写个从库,数据不能同步

异步复制

异步复制是一个主库,一个或多个从库,数据异步同步到从库

这种模式下,主节点不会主动推送数据到从节点,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理

这种模式下,如果主节点崩溃,此时主节点上已经提交的事务可能并没有传到从节点上,此时会将从节点提升为主节点,可能导致新主节点上的数据不完整

半同步复制

Mysql默认使用的是异步复制,由于异步操作所带来的延迟,当主库由于某种原因导致binlog日志的丢失,没有成功的同步到从库上,那么就会造成主从之间的不一致性。

原因为:异步复制中,主库在执行完对binlog的commit操作后即可返回客户端,无需等待binlog日志成功的传送到从库上

mysql中ddl是什么 mysql ddl dml dcl_mysql_02


而半同步复制执行时,为了保证主库中的binlog能够被可靠的复制到从库上,主库在每次成功提交事务后,并不是立即返回给客户端,而是等待binlog至少在一个从库上成功提交并写入到relaylog中。只有binlog成功的写入到了其中的一个从库中,主库才会给客户端反馈

一致性的保证:

  1. 直到至少一个从库的relay log成功保存了日志,主库才会给客户端反馈
  2. 如果在1、2、3操作,主库宕机,事务未提交成功,这时从库也没有收到bin log日志

注意

  1. 主库和从库都要启用半同步复制才会进行半同步复制功能,否则主库会还原为默认的异步复制
  2. 当主库等待超时时,也会还原为默认的异步复制。当至少有一个从库赶上时,主库会恢复到半同步复制

并行复制

基于DATABASE

开启并行复制后,会启动多个 Worker 线程,原有的 SQL 线程变为 Coordinator 线程。

可以并行的事务分发给 Worker 线程执行; 不能并行的事务等待 Worker 线程全部结束后,再由 Coordinator 线程自己执行。

DDL 语句或者是跨 Schema 的语句不能并行执行。

这种并行复制的模式,对于多个 DB 同时更新才能有较高的并行度,但是更常见的情况是更新集中在同个一个 DB。

一个简单的改进,把 Schema 级别的并行复制改成 Table 级别,可以大幅度提高单库多表环境下的并行度。但是对于只有一个热点表的情况依然处理不了。

基于LOGICAL_CLOCK

相比 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 引入了两个参数:

  • binlog_group_commit_sync_delay:等待延迟提交的时间,binlog提交后等待一段时间再 fsync。让每个 group 的事务更多,人为提高并行度。
  • binlog_group_commit_sync_no_delay_count:等待提交的最大事务数,如果等待时间没到,而事务数达到了,就立即 fsync。达到期望的并行度后立即提交,尽量缩小等待延迟。
基于 WriteSet 的并行复制

为了提高备库回放的速度,需要在主库尽量提高并行度。

8.0解决了这个问题,即使主库在串行提交的事务,只有互相不冲突,在备库就可以并行回放。

8.0 引入了参数 binlog_transaction_dependency_tracking 来控制事务依赖模式,让备库根据 commit timestamps 或者 write sets 并行回放事务,有三个取值:

  • COMMIT_ORDERE:使用 5.7 Group commit 的方式决定事务依赖
  • WRITESET:使用 WriteSet 的方式决定判定事务直接的冲突,发现冲突则依赖冲突事务,否则按照 COMMIT_ORDERE 方式决定依赖
  • WRITESET_SESSION:在 WRITESET 方式的基础上,保证同一个 session 内的事务不可并行

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维护工作量。