目录
trx_write_serialisation_history
1、-->PREPARED 或者 -->NOT_STARTED
一、前言
事务提交是事务即将落盘的一系列操作,涉及redo\undo log的写盘、bin log的写盘、事务状态的重置、各种参数的改变、无用undo log的清理等方方面面。
在commit过程会有两个阶段:一个是prepare阶段,入口函数为trx_prepare_low;另一个就是commit阶段。
prepare阶段和BINLOG做XA,分别设置insert undo 和 update undo的状态为prepare,调用函数trx_undo_set_state_at_prepare,过程也比较简单,找到undo log slot对应的头页面(trx_undo_t::hdr_page_no),将页面段头的TRX_UNDO_STATE设置为TRX_UNDO_PREPARED,同时修改其他对应字段。
commit阶段较为复杂,也是接下来要详细讲述的。
在InnoDB存储引擎层的commit阶段的入口函数为innobase_commit,它的总的结构大体如下:
二、基本概念
1、事务的状态
事务状态的宏定义在文件trx0types.h中,事务有五种状态,在源代码中的定义为:
其中每个参数的含义为:
参数名称 |
含义 |
TRX_STATE_NOT_STARTED |
事务尚未开始 |
TRX_STATE_FORCED_ROLLBACK |
事务强制回滚 |
TRX_STATE_ACTIVE |
事务处于活跃状态 |
TRX_STATE_PREPARED |
事务处于准备状态 |
TRX_STATE_COMMITTED_IN_MEMORY |
事务在内存中已提交 |
2、回滚日志的状态
回滚日志的状态的改变主要发生在trx_undo_set_state_at_finish函数,针对inisert和update两种类型的undo log做出不同的状态赋值。
三、逻辑分析
innobase_commit
在InnoDB存储引擎中进行事务的提交主要的调用的函数是innobase_commit,文件位于ha_innodb.cc。它的函数调用流程图为:
主要逻辑为:首先会判断是否将事务标记为异步回滚,如果是,则将事务回滚,调用的函数为innobase_rollback,如果不是,则会判断是否向MySQL 2PC协调器注册了事务。
接着提取出事务中read_only参数的值,判断是否标记为只读事务。调用thd_binlog_pos读取正在提交的事务的二进制日志位置。
接下来就是调用innobase_commit_low这个重要的函数,这个函数主要是在InnoDB数据库中提交一个事务。下一小节我们重点分析这个函数。
innobase commit完后,判断read_only参数,如果不是只读,则会将commit_threads数减1。检测的cond_signal,调用的函数为mysql_cond_signal。
接着就是执行写和刷新日志的操作。调用的函数为trx_copmmit_complete_for_mysql,将日志刷新到磁盘。
如果只是将sql语句标记位结束,并且不执行事务的提交。如果在此sql语句中为某些表保留了自动增量锁,则立即释放它,调用的函数为lock_unlock_table_autoinc。
并且将事务的undo_no保存,以便在必须回滚下一条sql语句时知道要回滚的位置。
最后重置所需的AUTO-INC行数和fts_next_doc_id,强制线程离开InnoDB,调用的函数为innobase_srv_conc_force_exit_innodb。