一条update语句在下面的方法开始一个事务
int handler::ha_update_row(const uchar *old_data, uchar *new_data)
{
int error;
DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
m_lock_type == F_WRLCK);
Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
/*
Some storage engines require that the new record is in record[0]
(and the old record is in record[1]).
*/
DBUG_ASSERT(new_data == table->record[0]);
DBUG_ASSERT(old_data == table->record[1]);
DBUG_ENTER("hanlder::ha_update_row");
DBUG_EXECUTE_IF("inject_error_ha_update_row",
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); );
MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
mark_trx_read_write();
DBUG_EXECUTE_IF("handler_crashed_table_on_usage",
my_error(HA_ERR_CRASHED, MYF(ME_ERRORLOG), table_share->table_name.str);
set_my_errno(HA_ERR_CRASHED);
return(HA_ERR_CRASHED););
MYSQL_TABLE_IO_WAIT(PSI_TABLE_UPDATE_ROW, active_index, error,
{ error= update_row(old_data, new_data);})
MYSQL_UPDATE_ROW_DONE(error);
if (unlikely(error))
DBUG_RETURN(error);
if (unlikely((error= binlog_log_row(table, old_data, new_data, log_func))))
DBUG_RETURN(error);
DBUG_RETURN(0);
}
但是事务的结束是在int
mysql_execute_command(THD *thd, bool first_level)方法中的最后
/* report error issued during command execution */
if (thd->killed_errno())
thd->send_kill_message();
if (thd->is_error() || (thd->variables.option_bits & OPTION_MASTER_SQL_ERROR))
trans_rollback_stmt(thd);
else
{
/* If commit fails, we should be able to reset the OK status. */
thd->get_stmt_da()->set_overwrite_status(true);
trans_commit_stmt(thd);
thd->get_stmt_da()->set_overwrite_status(false);
}
if (thd->killed == THD::KILL_QUERY ||
thd->killed == THD::KILL_TIMEOUT ||
thd->killed == THD::KILL_BAD_DATA)
是在事务提交之前进行的binlog写入。
提交事务的代码
thd->get_transaction()->merge_unsafe_rollback_flags();
if (thd->get_transaction()->is_active(Transaction_ctx::STMT))
{
res= ha_commit_trans(thd, FALSE);
if (! thd->in_active_multi_stmt_transaction())
trans_reset_one_shot_chistics(thd);
}
else if (tc_log)
res= tc_log->commit(thd, false);
if (res == FALSE && !thd->in_active_multi_stmt_transaction())
if (thd->rpl_thd_ctx.session_gtids_ctx().
notify_after_transaction_commit(thd))
sql_print_warning("Failed to collect GTID to send in the response packet!");
/* In autocommit=1 mode the transaction should be marked as complete in P_S */
DBUG_ASSERT(thd->in_active_multi_stmt_transaction() ||
thd->m_transaction_psi == NULL);
thd->get_transaction()->reset(Transaction_ctx::STMT);