
# MySQL主备复制原理简介
RDS for MySQL的默认备库、只读实例、自建备库、DRS链路灾备实例均采用MySQL的Binlog复制技术，也称为MySQL主备复制或主从复制技术。本章节介绍MySQL的主从复制原理。
#### 主备复制流程
![](https://support.huaweicloud.com/trouble-rds-mysql/zh-cn_image_0000002247143689.png "点击放大")
- 主节点（Master）中有数据更新时，会按照Binlog格式，将更新的操作以event形式写入到主节点的Binlog中。event有多种类型：INSERT、DELETE、UPDATE、QUERY等。
- 从节点（Slave）连接主节点时，有多少个从节点就会创建多少个Binlog dump线程。
- 当主节点的Binlog发生变化时，Binlog dump线程会通知所有从节点，并将相应Binlog内容推给从节点。
- 从节点的I/O thread收到Binlog内容后，会将内容写到本地relay log（中继日志）。
- 从节点的SQL thread会读取I/O thread写入的relay log，并且根据relay log中的event，回放对应的操作（DML、DDL等）。
 
#### Seconds_Behind_Master计算方式
Seconds_Behind_Master即主备复制时延，通过**show slave status**查询获取。Seconds_Behind_Master计算的伪代码实现如下：
```
if (SQL thread is running) 
//如果SQL线程启动
{
     if (SQL thread processed all the available relay log)
     //IO thread拉取主库Binlog的位置和sql thread应用的relay log相对于主库Binlog的位置相等
     {
         if (IO thread is running)
             //如果IO线程启动，设置延迟为0
             print 0;
         else
             //如果IO线程未启动，设置延迟为null
             print NULL;
     }
     else
         //如果SQL线程没有应用完所有的IO线程写入的event，那么需要计算Seconds_Behind_Master
         按公式计算Seconds_Behind_Master的值;
}  
else
     //如果SQL线程也没有启动，则设置为空值
     print NULL;
```
上述伪代码中，Seconds_Behind_Master的计算公式为：
Seconds_Behind_Master = time(0) - last_master_timestamp - clock_diff_with_master
相关变量含义如下：
1. time(0)：当前从节点服务器的系统时间。
2. clock_diff_with_master：从节点的系统时间和主节点服务器系统时间的差值，一般为0。如果主从节点系统时间不一致，那么计算出的从节点复制时延会不准确。
3. last_master_timestamp：从节点在回放relay log中event过程中计算和更新，该变量在并行复制（MTS）和非并行复制方式下，更新的时机是不同的，默认全部开启并行复制：
   - 并行复制：可以简单理解为，从节点的SQL线程在每个事务执行完成后，更新last_master_timestamp值，其更新是以事务为单位。所以大事务、DDL容易导致主备延迟大，具体请参见[主备复制时延持续增长后自动恢复](https://support.huaweicloud.com/trouble-rds-mysql/rds_12_0037.html)。
   
   - 非并行复制：从节点的SQL线程读取了relay log中的事务后，事务未执行前便会更新last_master_timestamp，其更新是以事务为单位。
    
 
综上所述，Seconds_Behind_Master的计算公式可以理解为：
Seconds_Behind_Master = 当前从节点服务器的系统时间 - 从节点SQL线程处理中事务在主节点的执行时间 - 从节点的系统时间和主节点服务器系统时间的差值
