From 8edc81b4c260c5600025952dee021a7600694e8a Mon Sep 17 00:00:00 2001 From: asahi Date: Tue, 26 Aug 2025 21:01:33 +0800 Subject: [PATCH] =?UTF-8?q?doc:=20=E9=98=85=E8=AF=BBmysql=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mysql/mysql文档/mysql_事务.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/mysql/mysql文档/mysql_事务.md b/mysql/mysql文档/mysql_事务.md index 47ea59b..f68de86 100644 --- a/mysql/mysql文档/mysql_事务.md +++ b/mysql/mysql文档/mysql_事务.md @@ -616,5 +616,31 @@ binlog机制mysql上层的,和存储引擎无关,而redo log机制是和存 - 如果事务可以在binlog被找到,那么事务将会被提交 - 如果事务在binlog中找不到,那么事务将会被回滚 -但是,上述实现需要确保`事务在engine中提交前binlog必须先被持久化`。故而,在上图中在调用`write`写入binlog后,还需要确保调用`fsync`来令binlog内容被刷新到磁盘文件中。 +> 如果`innodb_flush_log_at_trx_commit`被设置为1,那么在2pc的prepare阶段就被持久化到磁盘中,后续再对binlog进行write和fsync。故而,当执行crash recovery时,如果redo log为prepared状态,且对应事务在binlog中存在,那么事务在redo log中一定存在,可以直接对redo log进行commit;但如果事务在binlog中不存在,那么可以对innodb事务进行回滚。 +在大多场景下,如果binlog不存在,那么仅需对所有prepared transaction进行回滚即可。 + +> 当使用`on-line backup`方法(例如`Innodb Hot Backup`)时,这些工具会直接拷贝当前数据库的文件和innodb的transaction logs。但是,transaction logs也有可能包含prepared状态的事务。在通过备份恢复时,也会对所有prepared事务及逆行回滚,令数据库处于一致的状态。 +> +> 并且,`on-line backup`经常被用于启动新slave。`last committed transaction`在binary log中的log position被记录到了redo log header中,在recovery时,recovery program将会打印binary log中last committed transaction的位置。 + +##### prepare_commit_mutex +为了保证`on-line backup`行为的正确性,事务进行提交的顺序必须要和其被写入到binlog中的顺序一致,如果不能保证顺序的一致性,将会出现如下问题: +- 如果事务按照`T1, T2, T3`的顺序写入到binlog,但是其提交顺序为`T1, T3, T2`,那么将会导致根据binlog执行恢复时,binlog中间出现空洞:例如,T1和T3已经被提交,但是T2尚未被提交,导致binlog中T1和T3的binlog block都是commit,但是T2却是prepared + + + + + +> 上图中,事务提交顺序为`T2, T3`,但是binlog中的顺序为`T1, T2, T3`。从而导致位于binlog中最靠前位置的T1还未提交,为prepared状态;但是T2和T3的binlog处于commit状态,从而binlog发生空洞 + +在slave机器上发生recovery时,如果binlog存在空洞,slave将会直接跳过空洞,从而导致slave中事务缺失。 + +##### binary log group commit +`binary log group commit`实现将commit过程拆分为了如下图所示的多个阶段: + + + +上述stages位于binlog commit过程的内部,并且不会造成其他影响。由于commit过程被拆分为了如下stages,故而可以同时存在数个线程同时对事务进行处理,这样会增加吞吐量。 + +对于每个stage,都存在一个queue,session在queue中排队等待被处理。如果一个session被注册到了空的queue,那么其将被认为是stage leader,如果session被注册时queue不为空,那么其将作为stage follower。stage leader将会将queue中所有的threads移出stage,并且将leader和所有的followers注册到下个stage。 \ No newline at end of file