29 #include "trx0purge.ic"
62 #ifdef UNIV_PFS_RWLOCK
64 UNIV_INTERN mysql_pfs_key_t trx_purge_latch_key;
69 UNIV_INTERN mysql_pfs_key_t purge_sys_bh_mutex_key;
73 UNIV_INTERN my_bool srv_purge_view_update_only_debug;
82 trx_purge_graph_build(
85 ulint n_purge_threads)
96 for (i = 0; i < n_purge_threads; ++
i) {
114 ulint n_purge_threads,
136 ut_a(n_purge_threads > 0);
222 if (undo->
state != TRX_UNDO_CACHED) {
230 if (UNIV_UNLIKELY(undo->
id >= TRX_RSEG_N_SLOTS)) {
232 "InnoDB: Error: undo->id is %lu\n",
239 MONITOR_DEC(MONITOR_NUM_UNDO_SLOT_USED);
242 rseg_header + TRX_RSEG_HISTORY_SIZE,
MLOG_4BYTES, mtr);
248 rseg_header + TRX_RSEG_HISTORY_SIZE,
256 #ifdef HAVE_ATOMIC_BUILTINS
289 trx_purge_free_segment(
293 ulint n_removed_logs)
303 ibool marked = FALSE;
312 mutex_enter(&rseg->
mutex);
315 rseg->
space, rseg->zip_size, rseg->page_no, &mtr);
318 rseg->
space, rseg->zip_size, hdr_addr.
page, &mtr);
321 log_hdr = undo_page + hdr_addr.
boffset;
343 mutex_exit(&rseg->
mutex);
362 #ifdef HAVE_ATOMIC_BUILTINS
381 ut_ad(hist_size >= seg_size);
386 ut_ad(rseg->curr_size >= seg_size);
388 rseg->curr_size -= seg_size;
390 mutex_exit(&(rseg->
mutex));
399 trx_purge_truncate_rseg_history(
410 ulint n_removed_logs = 0;
415 mutex_enter(&(rseg->
mutex));
418 rseg->page_no, &mtr);
425 mutex_exit(&(rseg->
mutex));
433 hdr_addr.
page, &mtr);
435 log_hdr = undo_page + hdr_addr.
boffset;
439 if (undo_trx_no >= limit->
trx_no) {
441 if (undo_trx_no == limit->
trx_no) {
448 #ifdef HAVE_ATOMIC_BUILTINS
449 os_atomic_decrement_ulint(
459 n_removed_logs, &mtr);
461 mutex_exit(&(rseg->
mutex));
478 mutex_exit(&(rseg->
mutex));
481 trx_purge_free_segment(rseg, hdr_addr, n_removed_logs);
485 mutex_exit(&(rseg->
mutex));
490 mutex_enter(&(rseg->
mutex));
493 rseg->page_no, &mtr);
495 hdr_addr = prev_hdr_addr;
505 trx_purge_truncate_history(
522 for (i = 0; i < TRX_SYS_N_RSEGS; ++
i) {
527 trx_purge_truncate_rseg_history(rseg, limit);
537 trx_purge_rseg_get_next_history_log(
552 mutex_enter(&(rseg->
mutex));
569 (*n_pages_handled)++;
579 mutex_exit(&(rseg->
mutex));
595 " InnoDB: Warning: purge reached the"
596 " head of the history list,\n"
597 "InnoDB: but its length is still"
598 " reported as %lu! Make a detailed bug\n"
599 "InnoDB: report, and submit it"
600 " to http://bugs.mysql.com\n",
610 mutex_exit(&rseg->
mutex);
618 prev_log_addr.
page, &mtr)
627 mutex_enter(&(rseg->
mutex));
634 rseg_queue.
rseg = rseg;
649 mutex_exit(&rseg->
mutex);
658 trx_purge_get_rseg_with_min_trx_id(
678 purge_sys->
rseg = rseg;
682 purge_sys->
rseg = NULL;
684 return(ULINT_UNDEFINED);
697 zip_size = purge_sys->
rseg->zip_size;
714 trx_purge_read_undo_rec(
738 if (undo_rec != NULL) {
755 purge_sys->iter.
undo_no = undo_no;
767 trx_purge_choose_next_log(
void)
774 zip_size = trx_purge_get_rseg_with_min_trx_id(purge_sys);
776 if (purge_sys->
rseg != NULL) {
777 trx_purge_read_undo_rec(purge_sys, zip_size);
789 trx_purge_get_next_rec(
791 ulint* n_pages_handled,
810 zip_size = purge_sys->
rseg->zip_size;
812 offset = purge_sys->
offset;
818 trx_purge_rseg_get_next_history_log(
819 purge_sys->
rseg, n_pages_handled);
823 trx_purge_choose_next_log();
847 if (next_rec == NULL) {
858 if (type == TRX_UNDO_DEL_MARK_REC) {
869 if ((type == TRX_UNDO_UPD_EXIST_REC)
870 && !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
878 trx_purge_rseg_get_next_history_log(
879 purge_sys->
rseg, n_pages_handled);
883 trx_purge_choose_next_log();
888 space, zip_size, page_no, &mtr);
898 if (undo_page != page) {
900 (*n_pages_handled)++;
916 static __attribute__((warn_unused_result, nonnull))
918 trx_purge_fetch_next_rec(
921 ulint* n_pages_handled,
926 trx_purge_choose_next_log();
930 if (srv_print_thread_releases) {
932 "Purge: No logs left in the"
949 FALSE, purge_sys->
rseg->
id,
955 return(trx_purge_get_next_rec(n_pages_handled, heap));
963 trx_purge_attach_undo_recs(
965 ulint n_purge_threads,
972 ulint n_pages_handled = 0;
975 ut_a(n_purge_threads > 0);
977 *limit = purge_sys->iter;
981 thr != NULL && i < n_purge_threads;
998 ut_a(i == n_purge_threads);
1003 ut_a(n_thrs > 0 && thr != NULL);
1005 ut_ad(trx_purge_check_limit());
1029 *limit = purge_sys->iter;
1033 purge_rec->
undo_rec = trx_purge_fetch_next_rec(
1040 ib_heap_allocator_create(node->
heap),
1047 ib_vector_push(node->
undo_recs, purge_rec);
1049 if (n_pages_handled >= batch_size) {
1059 if (!(++i % n_purge_threads)) {
1066 ut_ad(trx_purge_check_limit());
1068 return(n_pages_handled);
1076 trx_purge_dml_delay(
void)
1098 delay = (ulint) ((ratio - .5) * 10000);
1115 trx_purge_wait_for_workers_to_complete(
1121 #ifdef HAVE_ATOMIC_BUILTINS
1123 while (!os_compare_and_swap_ulint(
1124 &purge_sys->
n_completed, n_submitted, n_submitted)) {
1131 #ifndef HAVE_ATOMIC_BUILTINS
1141 #ifndef HAVE_ATOMIC_BUILTINS
1146 #ifndef HAVE_ATOMIC_BUILTINS
1162 trx_purge_truncate(
void)
1165 ut_ad(trx_purge_check_limit());
1167 if (purge_sys->limit.
trx_no == 0) {
1168 trx_purge_truncate_history(&purge_sys->iter, purge_sys->
view);
1170 trx_purge_truncate_history(&purge_sys->limit, purge_sys->
view);
1181 ulint n_purge_threads,
1190 ut_a(n_purge_threads > 0);
1192 srv_dml_needed_delay = trx_purge_dml_delay();
1197 rw_lock_x_lock(&purge_sys->
latch);
1199 purge_sys->
view = NULL;
1205 rw_lock_x_unlock(&purge_sys->
latch);
1208 if (srv_purge_view_update_only_debug) {
1214 n_pages_handled = trx_purge_attach_undo_recs(
1215 n_purge_threads, purge_sys, &purge_sys->limit, batch_size);
1218 if (n_purge_threads > 1) {
1222 for (i = 0; i < n_purge_threads - 1; ++
i) {
1224 purge_sys->
query, thr);
1236 goto run_synchronously;
1248 os_atomic_inc_ulint(
1251 if (n_purge_threads > 1) {
1252 trx_purge_wait_for_workers_to_complete(purge_sys);
1259 if (purge_sys->limit.
trx_no == 0) {
1260 purge_sys->done = purge_sys->iter;
1262 purge_sys->done = purge_sys->limit;
1267 trx_purge_truncate();
1270 MONITOR_INC_VALUE(MONITOR_PURGE_INVOKED, 1);
1271 MONITOR_INC_VALUE(MONITOR_PURGE_N_PAGE_HANDLED, n_pages_handled);
1273 return(n_pages_handled);
1286 rw_lock_x_lock(&purge_sys->
latch);
1288 state = purge_sys->
state;
1290 rw_lock_x_unlock(&purge_sys->
latch);
1305 ut_a(srv_n_purge_threads > 0);
1307 rw_lock_x_lock(&purge_sys->
latch);
1315 state = purge_sys->
state;
1318 ib_logf(IB_LOG_LEVEL_INFO,
"Stopping purge");
1328 rw_lock_x_unlock(&purge_sys->
latch);
1338 rw_lock_x_lock(&purge_sys->
latch);
1345 "Waiting for purge to stop");
1349 rw_lock_x_unlock(&purge_sys->
latch);
1353 rw_lock_x_lock(&purge_sys->
latch);
1356 rw_lock_x_unlock(&purge_sys->
latch);
1359 MONITOR_INC_VALUE(MONITOR_PURGE_STOP_COUNT, 1);
1369 rw_lock_x_lock(&purge_sys->
latch);
1371 switch(purge_sys->
state) {
1382 if (purge_sys->
n_stop > 0) {
1388 if (purge_sys->
n_stop == 0) {
1390 ib_logf(IB_LOG_LEVEL_INFO,
"Resuming purge");
1395 MONITOR_INC_VALUE(MONITOR_PURGE_RESUME_COUNT, 1);
1400 rw_lock_x_unlock(&purge_sys->
latch);