Commit 347e22fb authored by Marko Mäkelä's avatar Marko Mäkelä

Merge bb-10.6-release into 10.6

parents a3e5b5c4 e5933b99
...@@ -1053,7 +1053,7 @@ class trx_sys_t ...@@ -1053,7 +1053,7 @@ class trx_sys_t
void close(); void close();
/** @return total number of active (non-prepared) transactions */ /** @return total number of active (non-prepared) transactions */
ulint any_active_transactions(); size_t any_active_transactions(size_t *prepared= nullptr);
/** /**
......
...@@ -1545,7 +1545,7 @@ void srv_master_callback(void*) ...@@ -1545,7 +1545,7 @@ void srv_master_callback(void*)
} }
/** @return whether purge should exit due to shutdown */ /** @return whether purge should exit due to shutdown */
static bool srv_purge_should_exit() static bool srv_purge_should_exit(size_t old_history_size)
{ {
ut_ad(srv_shutdown_state <= SRV_SHUTDOWN_CLEANUP); ut_ad(srv_shutdown_state <= SRV_SHUTDOWN_CLEANUP);
...@@ -1556,8 +1556,12 @@ static bool srv_purge_should_exit() ...@@ -1556,8 +1556,12 @@ static bool srv_purge_should_exit()
return true; return true;
/* Slow shutdown was requested. */ /* Slow shutdown was requested. */
size_t prepared, active= trx_sys.any_active_transactions(&prepared);
const size_t history_size= trx_sys.history_size(); const size_t history_size= trx_sys.history_size();
if (history_size)
if (!history_size);
else if (!active && history_size == old_history_size && prepared);
else
{ {
static time_t progress_time; static time_t progress_time;
time_t now= time(NULL); time_t now= time(NULL);
...@@ -1574,7 +1578,7 @@ static bool srv_purge_should_exit() ...@@ -1574,7 +1578,7 @@ static bool srv_purge_should_exit()
return false; return false;
} }
return !trx_sys.any_active_transactions(); return !active;
} }
/*********************************************************************//** /*********************************************************************//**
...@@ -1716,7 +1720,7 @@ inline void purge_coordinator_state::do_purge() ...@@ -1716,7 +1720,7 @@ inline void purge_coordinator_state::do_purge()
break; break;
} }
if (!srv_purge_should_exit()) if (!srv_purge_should_exit(history_size))
goto loop; goto loop;
} }
...@@ -1912,15 +1916,19 @@ ulint srv_get_task_queue_length() ...@@ -1912,15 +1916,19 @@ ulint srv_get_task_queue_length()
/** Shut down the purge threads. */ /** Shut down the purge threads. */
void srv_purge_shutdown() void srv_purge_shutdown()
{ {
if (purge_sys.enabled()) { if (purge_sys.enabled())
if (!srv_fast_shutdown && !opt_bootstrap) {
srv_update_purge_thread_count(innodb_purge_threads_MAX); if (!srv_fast_shutdown && !opt_bootstrap)
while(!srv_purge_should_exit()) { srv_update_purge_thread_count(innodb_purge_threads_MAX);
ut_a(!purge_sys.paused()); size_t history_size= trx_sys.history_size();
srv_wake_purge_thread_if_not_active(); while (!srv_purge_should_exit(history_size))
purge_coordinator_task.wait(); {
} history_size= trx_sys.history_size();
purge_sys.coordinator_shutdown(); ut_a(!purge_sys.paused());
srv_shutdown_purge_tasks(); srv_wake_purge_thread_if_not_active();
} purge_coordinator_task.wait();
}
purge_sys.coordinator_shutdown();
srv_shutdown_purge_tasks();
}
} }
...@@ -369,19 +369,6 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr) ...@@ -369,19 +369,6 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
undo = NULL; undo = NULL;
} }
MY_ATTRIBUTE((nonnull, warn_unused_result))
/** Remove undo log header from the history list.
@param[in,out] rseg rollback segment header page
@param[in] log undo log segment header page
@param[in] offset byte offset in the undo log segment header page
@param[in,out] mtr mini-transaction */
static dberr_t trx_purge_remove_log_hdr(buf_block_t *rseg, buf_block_t* log,
uint16_t offset, mtr_t *mtr)
{
return flst_remove(rseg, TRX_RSEG + TRX_RSEG_HISTORY, log,
uint16_t(offset + TRX_UNDO_HISTORY_NODE), mtr);
}
/** Free an undo log segment. /** Free an undo log segment.
@param block rollback segment header page @param block rollback segment header page
@param mtr mini-transaction */ @param mtr mini-transaction */
...@@ -391,7 +378,7 @@ static void trx_purge_free_segment(buf_block_t *block, mtr_t &mtr) ...@@ -391,7 +378,7 @@ static void trx_purge_free_segment(buf_block_t *block, mtr_t &mtr)
block->page.frame, &mtr)) block->page.frame, &mtr))
{ {
block->fix(); block->fix();
const page_id_t id{block->page.id()}; ut_d(const page_id_t id{block->page.id()});
mtr.commit(); mtr.commit();
/* NOTE: If the server is killed after the log that was produced /* NOTE: If the server is killed after the log that was produced
up to this point was written, and before the log from the mtr.commit() up to this point was written, and before the log from the mtr.commit()
...@@ -403,16 +390,8 @@ static void trx_purge_free_segment(buf_block_t *block, mtr_t &mtr) ...@@ -403,16 +390,8 @@ static void trx_purge_free_segment(buf_block_t *block, mtr_t &mtr)
log_free_check(); log_free_check();
mtr.start(); mtr.start();
block->page.lock.x_lock(); block->page.lock.x_lock();
if (UNIV_UNLIKELY(block->page.id() != id)) ut_ad(block->page.id() == id);
{ mtr.memo_push(block, MTR_MEMO_PAGE_X_MODIFY);
block->unfix();
block->page.lock.x_unlock();
block= buf_page_get_gen(id, 0, RW_X_LATCH, nullptr, BUF_GET, &mtr);
if (!block)
return;
}
else
mtr.memo_push(block, MTR_MEMO_PAGE_X_MODIFY);
} }
while (!fseg_free_step(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + while (!fseg_free_step(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER +
...@@ -434,7 +413,6 @@ trx_purge_truncate_rseg_history(trx_rseg_t& rseg, ...@@ -434,7 +413,6 @@ trx_purge_truncate_rseg_history(trx_rseg_t& rseg,
mtr.start(); mtr.start();
dberr_t err; dberr_t err;
reget:
buf_block_t *rseg_hdr= rseg.get(&mtr, &err); buf_block_t *rseg_hdr= rseg.get(&mtr, &err);
if (!rseg_hdr) if (!rseg_hdr)
{ {
...@@ -474,18 +452,16 @@ trx_purge_truncate_rseg_history(trx_rseg_t& rseg, ...@@ -474,18 +452,16 @@ trx_purge_truncate_rseg_history(trx_rseg_t& rseg,
TRX_UNDO_HISTORY_NODE); TRX_UNDO_HISTORY_NODE);
prev_hdr_addr.boffset= static_cast<uint16_t>(prev_hdr_addr.boffset - prev_hdr_addr.boffset= static_cast<uint16_t>(prev_hdr_addr.boffset -
TRX_UNDO_HISTORY_NODE); TRX_UNDO_HISTORY_NODE);
err= trx_purge_remove_log_hdr(rseg_hdr, b, hdr_addr.boffset, &mtr);
err= flst_remove(rseg_hdr, TRX_RSEG + TRX_RSEG_HISTORY, b,
uint16_t(hdr_addr.boffset + TRX_UNDO_HISTORY_NODE), &mtr);
if (UNIV_UNLIKELY(err != DB_SUCCESS)) if (UNIV_UNLIKELY(err != DB_SUCCESS))
goto func_exit; goto func_exit;
rseg_hdr->fix(); rseg_hdr->fix();
if (mach_read_from_2(b->page.frame + hdr_addr.boffset + TRX_UNDO_NEXT_LOG) || if (mach_read_from_2(b->page.frame + hdr_addr.boffset + TRX_UNDO_NEXT_LOG))
rseg.is_referenced() || /* We cannot free the entire undo log segment. */;
rseg.needs_purge > (purge_sys.head.trx_no
? purge_sys.head.trx_no
: purge_sys.tail.trx_no))
/* We cannot free the entire undo page. */;
else else
{ {
const uint32_t seg_size= const uint32_t seg_size=
...@@ -535,12 +511,7 @@ trx_purge_truncate_rseg_history(trx_rseg_t& rseg, ...@@ -535,12 +511,7 @@ trx_purge_truncate_rseg_history(trx_rseg_t& rseg,
log_free_check(); log_free_check();
mtr.start(); mtr.start();
rseg_hdr->page.lock.x_lock(); rseg_hdr->page.lock.x_lock();
if (UNIV_UNLIKELY(rseg_hdr->page.id() != rseg.page_id())) ut_ad(rseg_hdr->page.id() == rseg.page_id());
{
rseg_hdr->unfix();
rseg_hdr->page.lock.x_unlock();
goto reget;
}
mtr.memo_push(rseg_hdr, MTR_MEMO_PAGE_X_MODIFY); mtr.memo_push(rseg_hdr, MTR_MEMO_PAGE_X_MODIFY);
goto loop; goto loop;
...@@ -613,8 +584,9 @@ TRANSACTIONAL_TARGET static void trx_purge_truncate_history() ...@@ -613,8 +584,9 @@ TRANSACTIONAL_TARGET static void trx_purge_truncate_history()
{ {
ut_ad(rseg.is_persistent()); ut_ad(rseg.is_persistent());
rseg.latch.wr_lock(SRW_LOCK_CALL); rseg.latch.wr_lock(SRW_LOCK_CALL);
if (dberr_t e= trx_purge_truncate_rseg_history(rseg, head)) if (!rseg.is_referenced() && rseg.needs_purge <= head.trx_no)
err= e; if (dberr_t e= trx_purge_truncate_rseg_history(rseg, head))
err= e;
rseg.latch.wr_unlock(); rseg.latch.wr_unlock();
} }
......
...@@ -343,15 +343,29 @@ trx_sys_t::close() ...@@ -343,15 +343,29 @@ trx_sys_t::close()
} }
/** @return total number of active (non-prepared) transactions */ /** @return total number of active (non-prepared) transactions */
ulint trx_sys_t::any_active_transactions() size_t trx_sys_t::any_active_transactions(size_t *prepared)
{ {
uint32_t total_trx= 0; size_t total_trx= 0, prepared_trx= 0;
trx_sys.trx_list.for_each([&total_trx](const trx_t &trx) { trx_sys.trx_list.for_each([&](const trx_t &trx) {
if (trx.state == TRX_STATE_COMMITTED_IN_MEMORY || switch (trx.state) {
(trx.state == TRX_STATE_ACTIVE && trx.id)) case TRX_STATE_NOT_STARTED:
break;
case TRX_STATE_ACTIVE:
if (!trx.id)
break;
/* fall through */
case TRX_STATE_COMMITTED_IN_MEMORY:
total_trx++; total_trx++;
break;
case TRX_STATE_PREPARED:
case TRX_STATE_PREPARED_RECOVERED:
prepared_trx++;
}
}); });
if (prepared)
*prepared= prepared_trx;
return total_trx; return total_trx;
} }
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