Skip to content

Commit c25b496

Browse files
committed
MDEV-31382 SET GLOBAL innodb_undo_log_truncate=ON has no effect on logically empty undo logs
innodb_undo_log_truncate_update(): A callback function. If SET GLOBAL innodb_undo_log_truncate=ON, invoke srv_wake_purge_thread_if_not_active(). srv_wake_purge_thread_if_not_active(): If innodb_undo_log_truncate=ON, always wake up the purge subsystem. srv_do_purge(): If the history is empty, invoke trx_purge_truncate_history() in order to free undo log pages. trx_purge_truncate_history(): If head.trx_no==0, consider the cached undo logs to be free. trx_purge(): Remove the parameter "bool truncate" and let the caller invoke trx_purge_truncate_history() directly. Reviewed by: Vladislav Lesin
1 parent 3e40f9a commit c25b496

File tree

4 files changed

+43
-32
lines changed

4 files changed

+43
-32
lines changed

storage/innobase/handler/ha_innodb.cc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19684,10 +19684,17 @@ static MYSQL_SYSVAR_ULONG(purge_rseg_truncate_frequency,
1968419684
" purge rollback segment(s) on every Nth iteration of purge invocation",
1968519685
NULL, NULL, 128, 1, 128, 0);
1968619686

19687+
static void innodb_undo_log_truncate_update(THD *thd, struct st_mysql_sys_var*,
19688+
void*, const void *save)
19689+
{
19690+
if ((srv_undo_log_truncate= *static_cast<const my_bool*>(save)))
19691+
srv_wake_purge_thread_if_not_active();
19692+
}
19693+
1968719694
static MYSQL_SYSVAR_BOOL(undo_log_truncate, srv_undo_log_truncate,
1968819695
PLUGIN_VAR_OPCMDARG,
1968919696
"Enable or Disable Truncate of UNDO tablespace.",
19690-
NULL, NULL, FALSE);
19697+
NULL, innodb_undo_log_truncate_update, FALSE);
1969119698

1969219699
static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
1969319700
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,

storage/innobase/include/trx0purge.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,19 @@ Remove the undo log segment from the rseg slot if it is too big for reuse.
4343
@param[in,out] mtr mini-transaction */
4444
void
4545
trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr);
46+
47+
/**
48+
Remove unnecessary history data from rollback segments. NOTE that when this
49+
function is called, the caller (purge_coordinator_callback)
50+
must not have any latches on undo log pages!
51+
*/
52+
void trx_purge_truncate_history();
53+
4654
/**
4755
Run a purge batch.
4856
@param n_tasks number of purge tasks to submit to the queue
49-
@param truncate whether to truncate the history at the end of the batch
5057
@return number of undo log pages handled in the batch */
51-
ulint trx_purge(ulint n_tasks, bool truncate);
58+
ulint trx_purge(ulint n_tasks);
5259

5360
/** Rollback segements from a given transaction with trx-no
5461
scheduled for purge. */

storage/innobase/srv/srv0srv.cc

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,17 +1346,14 @@ static tpool::waitable_task purge_coordinator_task
13461346
static tpool::timer *purge_coordinator_timer;
13471347

13481348
/** Wake up the purge threads if there is work to do. */
1349-
void
1350-
srv_wake_purge_thread_if_not_active()
1349+
void srv_wake_purge_thread_if_not_active()
13511350
{
1352-
ut_ad(!srv_read_only_mode);
1351+
ut_ad(!srv_read_only_mode);
13531352

1354-
if (purge_sys.enabled() && !purge_sys.paused()
1355-
&& trx_sys.rseg_history_len) {
1356-
if(++purge_state.m_running == 1) {
1357-
srv_thread_pool->submit_task(&purge_coordinator_task);
1358-
}
1359-
}
1353+
if (purge_sys.enabled() && !purge_sys.paused() &&
1354+
(srv_undo_log_truncate || trx_sys.rseg_history_len) &&
1355+
++purge_state.m_running == 1)
1356+
srv_thread_pool->submit_task(&purge_coordinator_task);
13601357
}
13611358

13621359
/** @return whether the purge tasks are active */
@@ -1811,8 +1808,8 @@ static size_t srv_do_purge(ulint* n_total_purged)
18111808
n_threads = n_use_threads = srv_n_purge_threads;
18121809
srv_purge_thread_count_changed = 0;
18131810
} else if (trx_sys.rseg_history_len > rseg_history_len
1814-
|| (srv_max_purge_lag > 0
1815-
&& rseg_history_len > srv_max_purge_lag)) {
1811+
|| (srv_max_purge_lag > 0
1812+
&& rseg_history_len > srv_max_purge_lag)) {
18161813

18171814
/* History length is now longer than what it was
18181815
when we took the last snapshot. Use more threads. */
@@ -1838,15 +1835,19 @@ static size_t srv_do_purge(ulint* n_total_purged)
18381835

18391836
/* Take a snapshot of the history list before purge. */
18401837
if (!(rseg_history_len = trx_sys.rseg_history_len)) {
1841-
break;
1838+
n_pages_purged = 0;
1839+
goto truncate;
18421840
}
18431841

1844-
n_pages_purged = trx_purge(
1845-
n_use_threads,
1846-
!(++count % srv_purge_rseg_truncate_frequency)
1847-
|| purge_sys.truncate.current
1848-
|| (srv_shutdown_state != SRV_SHUTDOWN_NONE
1849-
&& srv_fast_shutdown == 0));
1842+
n_pages_purged = trx_purge(n_use_threads);
1843+
1844+
if (!(++count % srv_purge_rseg_truncate_frequency)
1845+
|| purge_sys.truncate.current
1846+
|| (srv_shutdown_state != SRV_SHUTDOWN_NONE
1847+
&& srv_fast_shutdown == 0)) {
1848+
truncate:
1849+
trx_purge_truncate_history();
1850+
}
18501851

18511852
*n_total_purged += n_pages_purged;
18521853
} while (n_pages_purged > 0 && !purge_sys.paused()

storage/innobase/trx/trx0purge.cc

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -522,10 +522,11 @@ __attribute__((optimize(0)))
522522
# endif
523523
#endif
524524
/**
525-
Removes unnecessary history data from rollback segments. NOTE that when this
526-
function is called, the caller must not have any latches on undo log pages!
525+
Remove unnecessary history data from rollback segments. NOTE that when this
526+
function is called, the caller (purge_coordinator_callback)
527+
must not have any latches on undo log pages!
527528
*/
528-
static void trx_purge_truncate_history()
529+
void trx_purge_truncate_history()
529530
{
530531
ut_ad(purge_sys.head <= purge_sys.tail);
531532
purge_sys_t::iterator &head= purge_sys.head.trx_no
@@ -618,7 +619,7 @@ static void trx_purge_truncate_history()
618619
for (const trx_undo_t *undo= UT_LIST_GET_FIRST(rseg->undo_cached); undo;
619620
undo= UT_LIST_GET_NEXT(undo_list, undo))
620621
{
621-
if (head.trx_no < undo->trx_id)
622+
if (head.trx_no && head.trx_no < undo->trx_id)
622623
goto not_free;
623624
else
624625
cached+= undo->size;
@@ -731,7 +732,7 @@ static void trx_purge_truncate_history()
731732
ut_ad(rseg->id == i);
732733
ut_ad(rseg->is_persistent());
733734
ut_ad(!rseg->trx_ref_count);
734-
ut_ad(rseg->needs_purge <= head.trx_no);
735+
ut_ad(!head.trx_no || rseg->needs_purge <= head.trx_no);
735736
ut_d(const auto old_page= rseg->page_no);
736737

737738
buf_block_t *rblock= trx_rseg_header_create(&space, i,
@@ -1235,9 +1236,8 @@ static void trx_purge_wait_for_workers_to_complete()
12351236
/**
12361237
Run a purge batch.
12371238
@param n_tasks number of purge tasks to submit to the queue
1238-
@param truncate whether to truncate the history at the end of the batch
12391239
@return number of undo log pages handled in the batch */
1240-
ulint trx_purge(ulint n_tasks, bool truncate)
1240+
ulint trx_purge(ulint n_tasks)
12411241
{
12421242
que_thr_t* thr = NULL;
12431243
ulint n_pages_handled;
@@ -1271,10 +1271,6 @@ ulint trx_purge(ulint n_tasks, bool truncate)
12711271

12721272
trx_purge_wait_for_workers_to_complete();
12731273

1274-
if (truncate) {
1275-
trx_purge_truncate_history();
1276-
}
1277-
12781274
MONITOR_INC_VALUE(MONITOR_PURGE_INVOKED, 1);
12791275
MONITOR_INC_VALUE(MONITOR_PURGE_N_PAGE_HANDLED, n_pages_handled);
12801276

0 commit comments

Comments
 (0)