MySQL5.5 开始支持半同步复制,但实现的不完善,slave ack 是在 master
commit 之后。如果 master 宕机,会有数据丢失的风险。如下图可以看出,主库在 commit 之后宕机,如果从库还未收到 binlog ,主从切换后可能会出现数据丢失的现象。
MySQL5.7 & AliSQL5.6 增加了 rpl_semi_sync_master_wait_point 参数来修复这个问题。先来看看这个参数是做什么用的。官方文档解释如下:
The rpl_semi_sync_master_wait_point system variable controls the point at which a semisynchronous replication master waits for slave acknowledgment of transaction receipt before returning a status to the client that committed the transaction.
简单来讲就是控制 master 在哪个环节接收 slave ack,master 接收到 ack 后返回状态给客户端。
此参数一共有两个选项 AFTER_SYNC(default) & AFTER_COMMIT。
我们先来看看旧的逻辑(AFTER_COMMIT):
AFTER_COMMIT: The master writes each transaction to its binary log and the slave, syncs the binary log, and commits the transaction to the storage engine. The master waits for slave acknowledgment of transaction receipt after the commit. Upon receiving acknowledgment, the master returns a result to the client, which then can proceed.
整个流程: master write binlog -> slave sync binlog -> master commit -> salve ack -> master return result。
这样会有什么问题呢?
With AFTER_COMMIT, the client issuing the transaction gets a return status only after the server commits to the storage engine and receives slave acknowledgment. After the commit and before slave acknowledgment, other clients can see the committed transaction before the committing client.
If something goes wrong such that the slave does not process the transaction, then in the event of a master crash and failover to the slave, it is possible that such clients will see a loss of data relative to what they saw on the master.
- 会出现脏读的情况,也就是在事务提交之后,slave 确认之前,客户端A还没有获得结果返回,但是客户端B能够读取A提交的结果;
- 可能会出现我们上文提到的数据丢失的问题;
这些问题对于数据一致性要求高的场景是无法满足的,所以 MySQL5.7 提供了 AFTER_SYNC 模式来避免这些问题。
AFTER_SYNC (the default): The master writes each transaction to its binary log and the slave, and syncs the binary log to disk. The master waits for slave acknowledgment of transaction receipt after the sync. Upon receiving acknowledgment, the master commits the transaction to the storage engine and returns a result to the client, which then can proceed.
整个流程: master write binlog -> slave sync binlog -> salve ack -> master commit -> master return result。这样就保证 master commit 的事务已经同步到 slave 了,防止数据丢失。
With AFTER_SYNC, all clients see the committed transaction at the same time: After it has been acknowledged by the slave and committed to the storage engine on the master. Thus, all clients see the same data on the master.
In the event of master failure, all transactions committed on the master have been replicated to the slave (saved to its relay log). A crash of the master and failover to the slave is lossless because the slave is up to date.
- 保证所有客户端查询到的结果都是相同的;
- 保证 slave 不会丢数据;
- master 宕机虽然不会导致数据丢失,但有一种情况可能会出现,那就是 salve 的数据比 master 多,大家可以回顾下流程,想想为什么,该如何处理。
AliSQL5.6 半同步复制已经实现此功能,并且是整合到主代码里原生支持的,而 MySQL 半同步是通过插件的形式支持