MySQL主备复制原理说明
MySQL复制是基于复制源服务器在其二进制日志(下称binlog)中跟踪对其数据库的所有更改(增、删、改等)。binlog作为从服务器启动那一刻起修改数据库结构或内容(数据)的所有事件的书面记录。通常,SELECT不记录语句是因为它们既不修改数据库结构也不修改数据本身。
连接到源的每个副本都请求binlog的副本。也就是说,它从源中拉取数据,而不是源将数据推送到副本。副本还执行它接收到的binlog中的事件。这具有重复原始更改的效果,就像它们在源上所做的一样。创建表或修改其结构,并根据最初在源上所做的更改插入、删除和更新数据。
因为每个副本都是独立的,所以来自源的binlog的更改的重播独立发生在连接到源的每个副本上。此外,因为每个副本仅通过从源请求它来接收binlog的副本,副本能够按照自己的节奏读取和更新数据库的副本,并且可以随意启动和停止复制过程而不会影响在源端或副本端更新到最新数据库状态的能力。
主备复制流程说明:
- 主库节点中每当有数据进行DML操作时,事务会按照binlog格式将DML操作以event的形式写入到主节点的binlog中。DML包括:Insert, Delete, Update等。
- 备库节点连接主库节点时,有多少个备节点就会创建多少个binlog dump线程。
- 当主库节点的binlog发生变化时,binlog dump线程会通知备节点(若多个备库则通知所有备节点),并将相应的binlog内容推送给备库节点。
- 备库节点的I/O thread进程收到binlog后,会将日志包含的内容写入本地中继日志(下称relay log)。
- 备库节点的SQL thread会读取I/O thread写入的relay log并根据relay log中记录的event内容生成相应的DML语句,回放入备库中,完成整个主备复制流程。
主要源码说明:
/*
The pseudo code to compute Seconds_Behind_Master: 信息来自源码sql/rpl_replica.cc
if (SQL thread is running)
//如果SQL thread启动
{
if (SQL thread processed all the available relay log)
//当IO thread拉取主库binlog的位置和SQL thread应用的relay log相对于主库binlog的位置相等时
{
if (IO thread is running)
//如果IO thread启动,设置延迟为0
print 0;
else
//如果未启动,设置延迟为NULL
print NULL;
}
else
//如果SQL thread没有应用完所有IO thread写入的event时,需要计算Seconds_Behind_Master
compute Seconds_Behind_Master;
}
else
//如果SQL thread也没启动,则设置为NULL
print NULL;
*/
Seconds_Behind_Master的计算公式:Seconds_Behind_Master = time(0) - last_master_timestamp - clock_diff_with_master。
公式变量解释:
- time(0):当前备库节点服务器的系统时间。
- last_master_timestamp:备库节点在回放relay log中的event过程中的计算和更新,该变量可理解为备库节点SQL thread处理中事务在主库节点中的执行时间。
- clock_diff_with_master:备库节点的系统时间和主库节点服务器系统时间的差值,一般为0。如果主备节点系统时间不一致,那计算出的备库节点复制时延会不准确。
综上所述:Seconds_Behind_Master = 当前备库节点服务器的系统时间 - 备库节点SQL线程处理中事务在主库节点的执行时间 - 备库节点的系统时间和主库节点服务器系统时间的差值。