作者:高鹏
文章末尾有他著作的《深入理解MySQL主从原理 32讲》,深入透彻理解MySQL主从,GTID相关技术知识。本文节选自《深入理解MySQL主从原理》第15节本节包含一个笔记如下:
https://www.jianshu.com/writer#/notebooks/37013486/notes/50142567
本文提要
本节将解释 MySQL 层详细的提交流程,但是由于能力有限,这里不可能包含全部的步骤,只是包含了一些重要的、并且我学习过的步骤。
我们首先需要来假设参数设置,因为某些参数的设置会直接影响到提交流程,我们也会逐一解释这些参数的含义。
本节介绍的大部分内容都集中在函数 MYSQL_BIN_LOG::prepare和MYSQL_BIN_LOG::ordered_commit 之中。
一、参数设置
本部分假定参数设置为:
- binlog_group_commit_sync_delay:0
- binlog_group_commit_sync_no_delay_count:0
- binlog_order_commits:ON
- sync_binlog:1
- binlog_transaction_dependency_tracking:COMMIT_ORDER
关于参数 binlog_transaction_dependency_tracking 需要重点说明一下。我们知道 Innodb 的行锁是在语句运行期间就已经获取,因此如果多个事务同时进入了提交流程(prepare阶段),在 Innodb 层提交释放 Innodb 行锁资源之前各个事务之间肯定是没有行冲突的,因此可以在从库端并行执行。在基于 COMMIT_ORDER 的并行复制中,last commit 和 seq number 正是基于这种思想生成的,如果 last commit 相同则视为可以在从库并行回放,在19节我们将解释从库判定并行回放的规则。而在基于 WRITESET 的并行复制中,last commit 将会在 WRITESET 的影响下继续降低,来使从库获得更好的并行回放效果,但是它也是 COMMIT_ORDER 为基础的,这个下一节将讨论。我们这节只讨论基于COMMIT_ORDER 的并行复制中 last commit 和 seq number 的生成方式。
而sync_binlog参数则有两个功能:
- sync_binlog=0:binary log 不 sync 刷盘,依赖于 OS 刷盘机制。同时会在flush阶段后通知DUMP线程发送Event。
- sync_binlog=1:binary log 每次 sync 队列形成后都进行sync刷盘,约等于每次group commit 进行刷盘。同时会在 sync 阶段后通知DUMP线程发送 Event。注意sync_binlog 非1的设置可能导致从库比主库多事务。
after_commit(5.6默认):master将每个事务写入binlog(sync_binlog=1),传递到slave刷新到磁盘(sync_relay=1),同时主库提交事务(此时数据已经提交了)。master等待slave反馈收到relay log,只有收到ACK后master才将commit OK结果反馈给客户端。
after_sync(5.7默认):master将每个事务写入binlog , 传递到slave刷新到磁盘(relay log)。master等待slave反馈接收到relay log的ack之后,再提交事务并且返回commit OK结果给客户端。 即使主库crash,所有在主库上已经提交的事务都能保证已经同步到slave的relay log中。
区别:
1,ACK的时间点不同:
(1)半同步复制在InnoDB层的Commit Log后等待ACK,主从切换会有数据丢失风险。
(2)无损复制在MySQL Server层的Write binlog后等待ACK,主从切换会有数据变多风险。
2,主从数据一致性:
(1)半同步复制意味着在Master节点上,这个刚刚提交的事物对数据库的修改,对其他事物是可见的。因此,如果在等待Slave ACK的时候crash了,那么会对其他事务出现幻读,数据丢失
(2)无损复制在write binlog完成后,就传输binlog,但还没有去写commit log,意味着当前这个事物对数据库的修改,其他事物也是不可见的。因此,不会出现幻读和数据丢失风险。
- sync_binlog>1:binary log 将在指定次 sync 队列形成后进行 sync 刷盘,约等于指定次 group commit 后刷盘。同时会在 flush 阶段后通知 DUMP 线程发送 Event。
二,步骤解析第一阶段:prepare阶段
注意:在第1步之前会有一个获取 MDL_key::COMMIT