Commit 5fea8ffc authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-30100 preparation: Simplify InnoDB transaction commit further

trx_commit_complete_for_mysql(): Remove some conditions.
We will rely on trx_flush_log_if_needed().

trx_t::must_flush_log_later: Remove. trx_commit_complete_for_mysql()
can simply check for trx_t::flush_log_later.

trx_t::commit_in_memory(): Treat flush_log_later as input and output.

trx_flush_log_if_needed_low(): Renamed to trx_flush_log_if_needed().
Assert that innodb_flush_log_at_trx_commit!=0 was checked by
the caller and that the transaction is not in XA PREPARE state.

trx_write_serialisation_history(): Move some code from
trx_purge_add_undo_to_history().

trx_prepare(): Invoke log_write_up_to() directly if needed.

innobase_commit_ordered_2(): Remove a condition, and do not reset
trx_t::flush_log_later, because it must be passed from
trx_t::commit_in_memory() to trx_commit_complete_for_mysql().
parent be983bec
...@@ -4499,11 +4499,7 @@ innobase_commit_ordered_2( ...@@ -4499,11 +4499,7 @@ innobase_commit_ordered_2(
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
innobase_commit_low(trx); innobase_commit_low(trx);
trx->mysql_log_file_name = NULL;
if (!read_only) {
trx->mysql_log_file_name = NULL;
trx->flush_log_later = false;
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -772,12 +772,6 @@ struct trx_t : ilist_node<> ...@@ -772,12 +772,6 @@ struct trx_t : ilist_node<>
defer flush of the logs to disk defer flush of the logs to disk
until after we release the until after we release the
mutex. */ mutex. */
bool must_flush_log_later;/*!< set in commit()
if flush_log_later was
set and redo log was written;
in that case we will
flush the log in
trx_commit_complete_for_mysql() */
ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */ ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */
/** whether this modifies InnoDB dictionary tables */ /** whether this modifies InnoDB dictionary tables */
bool dict_operation; bool dict_operation;
......
...@@ -268,12 +268,7 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr) ...@@ -268,12 +268,7 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
ut_ad(mach_read_from_2(undo_header + TRX_UNDO_NEEDS_PURGE) <= 1); ut_ad(mach_read_from_2(undo_header + TRX_UNDO_NEEDS_PURGE) <= 1);
ut_ad(rseg->needs_purge > trx->id); ut_ad(rseg->needs_purge > trx->id);
ut_ad(rseg->last_page_no != FIL_NULL);
if (rseg->last_page_no == FIL_NULL)
{
rseg->last_page_no= undo->hdr_page_no;
rseg->set_last_commit(undo->hdr_offset, trx->rw_trx_hash_element->no);
}
rseg->history_size++; rseg->history_size++;
......
...@@ -419,7 +419,6 @@ void trx_t::free() ...@@ -419,7 +419,6 @@ void trx_t::free()
MEM_NOACCESS(&active_commit_ordered, sizeof active_commit_ordered); MEM_NOACCESS(&active_commit_ordered, sizeof active_commit_ordered);
MEM_NOACCESS(&check_unique_secondary, sizeof check_unique_secondary); MEM_NOACCESS(&check_unique_secondary, sizeof check_unique_secondary);
MEM_NOACCESS(&flush_log_later, sizeof flush_log_later); MEM_NOACCESS(&flush_log_later, sizeof flush_log_later);
MEM_NOACCESS(&must_flush_log_later, sizeof must_flush_log_later);
MEM_NOACCESS(&duplicates, sizeof duplicates); MEM_NOACCESS(&duplicates, sizeof duplicates);
MEM_NOACCESS(&dict_operation, sizeof dict_operation); MEM_NOACCESS(&dict_operation, sizeof dict_operation);
MEM_NOACCESS(&dict_operation_lock_mode, sizeof dict_operation_lock_mode); MEM_NOACCESS(&dict_operation_lock_mode, sizeof dict_operation_lock_mode);
...@@ -993,12 +992,14 @@ static void trx_write_serialisation_history(trx_t *trx, mtr_t *mtr) ...@@ -993,12 +992,14 @@ static void trx_write_serialisation_history(trx_t *trx, mtr_t *mtr)
{ {
mysql_mutex_lock(&purge_sys.pq_mutex); mysql_mutex_lock(&purge_sys.pq_mutex);
trx_sys.assign_new_trx_no(trx); trx_sys.assign_new_trx_no(trx);
const trx_id_t end{trx->rw_trx_hash_element->no};
/* If the rollback segment is not empty, trx->no cannot be less /* If the rollback segment is not empty, trx->no cannot be less
than any trx_t::no already in rseg. User threads only produce than any trx_t::no already in rseg. User threads only produce
events when a rollback segment is empty. */ events when a rollback segment is empty. */
purge_sys.purge_queue.push(TrxUndoRsegs(trx->rw_trx_hash_element->no, purge_sys.purge_queue.push(TrxUndoRsegs{end, *rseg});
*rseg));
mysql_mutex_unlock(&purge_sys.pq_mutex); mysql_mutex_unlock(&purge_sys.pq_mutex);
rseg->last_page_no= undo->hdr_page_no;
rseg->set_last_commit(undo->hdr_offset, end);
} }
else else
trx_sys.assign_new_trx_no(trx); trx_sys.assign_new_trx_no(trx);
...@@ -1086,10 +1087,10 @@ extern "C" void thd_decrement_pending_ops(MYSQL_THD); ...@@ -1086,10 +1087,10 @@ extern "C" void thd_decrement_pending_ops(MYSQL_THD);
@param trx transaction; if trx->state is PREPARED, the function will @param trx transaction; if trx->state is PREPARED, the function will
also wait for the flush to complete. also wait for the flush to complete.
*/ */
static void trx_flush_log_if_needed_low(lsn_t lsn, const trx_t *trx) static void trx_flush_log_if_needed(lsn_t lsn, trx_t *trx)
{ {
if (!srv_flush_log_at_trx_commit) ut_ad(srv_flush_log_at_trx_commit);
return; ut_ad(trx->state != TRX_STATE_PREPARED);
if (log_sys.get_flushed_lsn() > lsn) if (log_sys.get_flushed_lsn() > lsn)
return; return;
...@@ -1097,39 +1098,18 @@ static void trx_flush_log_if_needed_low(lsn_t lsn, const trx_t *trx) ...@@ -1097,39 +1098,18 @@ static void trx_flush_log_if_needed_low(lsn_t lsn, const trx_t *trx)
const bool flush= srv_file_flush_method != SRV_NOSYNC && const bool flush= srv_file_flush_method != SRV_NOSYNC &&
(srv_flush_log_at_trx_commit & 1); (srv_flush_log_at_trx_commit & 1);
if (trx->state == TRX_STATE_PREPARED)
{
/* XA, which is used with binlog as well.
Be conservative, use synchronous wait.*/
sync:
log_write_up_to(lsn, flush);
return;
}
completion_callback cb; completion_callback cb;
if ((cb.m_param = thd_increment_pending_ops(trx->mysql_thd))) if ((cb.m_param= thd_increment_pending_ops(trx->mysql_thd)))
{ {
cb.m_callback = (void (*)(void *)) thd_decrement_pending_ops; cb.m_callback = (void (*)(void *)) thd_decrement_pending_ops;
log_write_up_to(lsn, flush, false, &cb); log_write_up_to(lsn, flush, false, &cb);
} }
else else
goto sync; {
} trx->op_info= "flushing log";
log_write_up_to(lsn, flush);
/**********************************************************************//** trx->op_info= "";
If required, flushes the log to disk based on the value of }
innodb_flush_log_at_trx_commit. */
static
void
trx_flush_log_if_needed(
/*====================*/
lsn_t lsn, /*!< in: lsn up to which logs are to be
flushed. */
trx_t* trx) /*!< in/out: transaction */
{
trx->op_info = "flushing log";
trx_flush_log_if_needed_low(lsn, trx);
trx->op_info = "";
} }
/** Process tables that were modified by the committing transaction. */ /** Process tables that were modified by the committing transaction. */
...@@ -1239,7 +1219,6 @@ TRANSACTIONAL_INLINE inline void trx_t::commit_in_memory(const mtr_t *mtr) ...@@ -1239,7 +1219,6 @@ TRANSACTIONAL_INLINE inline void trx_t::commit_in_memory(const mtr_t *mtr)
{ {
/* We already detached from rseg in trx_write_serialisation_history() */ /* We already detached from rseg in trx_write_serialisation_history() */
ut_ad(!rsegs.m_redo.undo); ut_ad(!rsegs.m_redo.undo);
must_flush_log_later= false;
read_view.close(); read_view.close();
if (is_autocommit_non_locking()) if (is_autocommit_non_locking())
...@@ -1343,11 +1322,9 @@ TRANSACTIONAL_INLINE inline void trx_t::commit_in_memory(const mtr_t *mtr) ...@@ -1343,11 +1322,9 @@ TRANSACTIONAL_INLINE inline void trx_t::commit_in_memory(const mtr_t *mtr)
commit_lsn= undo_no || !xid.is_null() ? mtr->commit_lsn() : 0; commit_lsn= undo_no || !xid.is_null() ? mtr->commit_lsn() : 0;
if (!commit_lsn) if (!commit_lsn)
/* Nothing to be done. */; flush_log_later= false;
else if (flush_log_later) else if (flush_log_later);
/* Do nothing yet */ else if (!(flush_log_later= !srv_flush_log_at_trx_commit))
must_flush_log_later= true;
else if (srv_flush_log_at_trx_commit)
trx_flush_log_if_needed(commit_lsn, this); trx_flush_log_if_needed(commit_lsn, this);
} }
...@@ -1603,16 +1580,18 @@ trx_commit_complete_for_mysql( ...@@ -1603,16 +1580,18 @@ trx_commit_complete_for_mysql(
/*==========================*/ /*==========================*/
trx_t* trx) /*!< in/out: transaction */ trx_t* trx) /*!< in/out: transaction */
{ {
if (trx->id != 0 if (!trx->flush_log_later)
|| !trx->must_flush_log_later return;
|| (srv_flush_log_at_trx_commit == 1 && trx->active_commit_ordered)) { trx->flush_log_later= false;
return;
}
trx_flush_log_if_needed(trx->commit_lsn, trx);
trx->must_flush_log_later = false; switch (srv_flush_log_at_trx_commit) {
case 0:
return;
case 1:
if (trx->active_commit_ordered)
return;
}
trx_flush_log_if_needed(trx->commit_lsn, trx);
} }
/**********************************************************************//** /**********************************************************************//**
...@@ -1873,8 +1852,10 @@ trx_prepare( ...@@ -1873,8 +1852,10 @@ trx_prepare(
gather behind one doing the physical log write to disk. gather behind one doing the physical log write to disk.
We must not be holding any mutexes or latches here. */ We must not be holding any mutexes or latches here. */
if (auto f = srv_flush_log_at_trx_commit) {
trx_flush_log_if_needed(lsn, trx); log_write_up_to(lsn, (f & 1) && srv_file_flush_method
!= SRV_NOSYNC);
}
if (!UT_LIST_GET_LEN(trx->lock.trx_locks) if (!UT_LIST_GET_LEN(trx->lock.trx_locks)
|| trx->isolation_level == TRX_ISO_SERIALIZABLE) { || trx->isolation_level == TRX_ISO_SERIALIZABLE) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment