主从同步
主从同步的过程如下图所示,核心就是,当从库连接上主库之后,主库为为这个从库创建一个dump线程,用于传输binlog。从库有一个IO线程来接收binlog并写入它的中转日志relay log,同时有一个SQL线程读取relay log进行执行。主从同步保证的是数据的最终一致性。主从同步的方式包括:
- 异步复制,主库事务完成就立刻返回客户端,不关心是否复制到从库上 (默认采取异步复制)
- 同步复制,主库事务完成后要等待所有从库都复制了这个事务,才返回成功给客户端
- 半同步复制,主库事务完成后,至少一个从库接收并写到relay log才返回成功给客户端
主从同步什么时候pull,什么时候push?答案是都有。当slave连上master,会告知master它目前的binlog fileName和同步位点pos, master收到后,会找到该文件并把剩下的binlog发给slave,这其实就是pull。当连接进行时,master侧有新的binlo*生时,主线程会广播dump thread有新binlo*生,然后再发给slave,也就是push。
主备延迟
主备延迟的定义:同一个事务,在主库执行完成到从库执行完成的这个时间差。根据主从同步的过程,我们可以把过程切割成3个时间点:
- 主库写入binlog的时间点t1
- 从库接收到binlog的时间点t2
- 从库写入数据更新的时间点t3
t1其实就是事务完成的时间(算主备延迟的起始时间点);t2-t1主要就是网络开销,正常情况下是很小的。所以主备延迟主要是来自于t3-t2即从库执行relay log的时间/消费中转日志的时间。
导致t3-t2时间较大的原因,有以下几点:
- 从库的规格/机器性能比主库差
- 从库的压力比较大。例如,放了很多运营查询/分析的语句到从库执行。这种情况解决的办法有:一主多从,或者将binlog输出到外部系统如hadoop,来提供统计查询等能力,核心就是分担从库压力
- 大事务。假设一个事务在主库执行5分钟,那么在从库也会延迟5分钟。
主备一致
那么在主从同步的过程会不会出现主备数据不一致的问题呢?其实是有可能的。在日志模块,我们提到,binlog_format其实根本上有两种,一种是statement(SQL语句本身),一种是row(影响修改的行信息和事件)。
例如日志模块提到的这个栗子