花了两天的时间,大概了解了下Innodb部分跟事务相关的函数代码,其实也就那么几个函数,但每个函数会把几种情况放在一起处理
下面是我整理的关于XA事务、普通事务以及单独语句的函数调用,做个记录,主要用来在gdb代码的时候,做断点用。
xa start 'pp'
trans_xa_start
trans_begin (隐含的commit任何当前的事务并释放锁)
trans_check :()
(likely(value)、unlikely(value))
ha_commit_trans()
thd->mdl_context.release_transactional_locks()
trans_commit_stmt
mysql> insert into x4 values(5);
trans_commit_stmt
ha_commit_trans
binlog_prepare:空函数
innobase_xa_prepare 对于xa事务,仅仅标记为ended
……
ha_commit_one_phase
binlog_commit(该函数在每执行一次statement后)
cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF)
//binlog_commit_flush_trx_cache:将binlog cache中的内容写到文件中。
//binlog_flush_cache
innobase_commit (对这条语句而言,仅仅标记该语句结束了,而不做commit)
mysql> xa end 'pp';
trans_commit_stmt
after_commit
mysql> xa prepare 'pp';
trans_xa_prepare
ha_prepare
binlog_prepare
innobase_xa_prepare
……
trx_prepare_for_mysql
trx_prepare_off_kernel-------根据my.cnf的选项决定是否刷新log到磁盘----做一次group
commit
当不为XA_PREPARE语句时。。。
if (thd_sql_command(thd) != SQLCOM_XA_PREPARE
pthread_mutex_lock(&prepare_commit_mutex);
trans_commit_stmt
after_commit
mysql> xa commit 'pp';
trans_xa_commit
92 加锁……
ha_commit_one_phase(thd, 1)
binlog_commit
binlog_commit_flush_trx_cache
binlog_flush_cache
innobase_commit
innobase_commit_low
trx_commit_for_mysql
trx_commit_off_kernel(看起来似乎是真的要提交了。。。。)
if (trx->declared_to_be_inside_innodb) {
//不知道为什么没有持有prepare_commit_mutex
trx_commit_complete_for_mysql
log_write_up_to:(log0log.c)
实现group commit,这里仅考虑flushto_disk为真的情况,即需要向磁盘中fsync log
loop:
当ut_dulint_cmp(log_sys->flushed_to_disk_lsn, lsn) >= 0
即lsn小于或等于全局变量log_sys中的记录的上次刷新的lsn时,直接返回
log_sys->n_pending_writes > 0
if (flush_to_disk
&&
ut_dulint_cmp(log_sys->current_flush_lsn, lsn)
>= 0) {
goto do_waits;
}
///
log-bin = 1
sync_binlog = 1
------------------------------------------
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
trans_begin()
trans_commit_stmt
mysql> insert into x4 values (10);
Query OK, 1 row affected (1 min 1.69 sec)
trans_commit_stmt
ha_commit_trans
binlog_prepare
innobase_xa_prepare
ha_commit_one_phase
binlog_commit(看起来什么也没做,仅仅做了cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF);)
cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF);
innobase_commit(同样仅仅是做一些标记)
mysql> commit ;
trans_commit
ha_commit_trans
binlog_prepare
innodb_xa_prepare
trx_prepare_for_mysql
mysql_mutex_lock(&prepare_commit_mutex);
MYSQL_BIN_LOG::log_xid
ha_commit_one_phase
binlog_commit(似乎木有做写binlog,莫非已经被group commit了。。。= =!
log_xid..)
innobase_commit
innobase_commit_low
mysql_mutex_unlock(&prepare_commit_mutex);
trx_commit_complete_for_mysql(trx);
trans_commit_stmt
---------------------------------------------
单独执行一条语句:
mysql> insert into x4 values (11);
trans_commit_stmt()
ha_commit_trans()
binlog_prepare
innobase_xa_prepare
trx_prepare_for_mysql
mysql_mutex_lock(&prepare_commit_mutex);
if (error
|| (is_real_trans && xid &&
(error= !(cookie= tc_log->log_xid(thd,
xid)))))
ha_commit_one_phase
binlog_commit
innobase_commit
innobase_commit_low(trx);
mysql_mutex_unlock(&prepare_commit_mutex);
trx_commit_complete_for_mysql(trx);