1.主从复制

image.png

  1. 主节点开启binlog(设置log-bin参数),主库的增删改被记录到binlog中
  2. 从节点通过mysql协议,请求主节点binlog中的event
  3. 主库创建一个binlog dump thread线程,把从节点发送的位置标示和自己本地比较,如果没有发送参数,则从文件的第一个event开始发送
  4. 从库启动以后启动一个I/O线程读取binlog并写入到relaylog,并记录读取主节点位置
  5. 从库启动后创建一个SQL线程,从relaylog中读取内容更新到库中

主库为每个从库分配一个binlog dump thread线程
上述过程为异步同步,还有其他方式
1.全同步方式:主库执行事务,从库每个都同步完了主库才能提交事务,但这样耗时长
2.半同步复制:主库收到至少一个从节点同步完成,就完成事务,从库完成写入relaylog无需等待sql线程写入数据,就记为完成
image.png
这是采用after commit方式的半同步复制,先本地落库,再去同步binlog,但是会存在问题
1.从节点没有收到binlog,客户端会收到事务提交失败,则重新提交,原先的主节点变成从节点后,会收到新的主节点发送过来的binlog,就会重复执行事务
2.从节点收到了binlog,客户端会受到事务提交失败,则重新提交,这个节点就会重复执行事务

所以mysql在5.7启用了一种新的模式叫after sync(原先模式也保留),就是storage commit和waiting slave dump互换位置
参考:
https://blog.csdn.net/zai_xia/article/details/90379016
https://www.cnblogs.com/ivictor/p/5735580.html

2.binlog和redolog

为保证数据一致性,采用二阶段提交方式
image.png
第一阶段:InnoDB Prepare阶段,此时sql已经执行完成,生成事务id并写redolog和undolog内存日志,但这个时候只记录了操作日志,没有记录事务提交commit日志,此时事务为Prepare阶段
第二阶段:第一步先写binlog到内存中,再fsync同步到磁盘中,第二步提交commit到redolog中

  • 如果在写入binglog前宕机,恢复时,mysql会认为这个事务没有执行完成,会回滚日志
  • 如果在写入binglog后宕机,恢复时,mysql会先看binlog是否录入,binlog录入就算执行成功

参考链接