29 #include "trx0purge.ic"
54 #ifdef UNIV_PFS_RWLOCK
56 UNIV_INTERN mysql_pfs_key_t trx_purge_latch_key;
61 UNIV_INTERN mysql_pfs_key_t purge_sys_bh_mutex_key;
76 #ifdef UNIV_SYNC_DEBUG
95 trx_purge_arr_store_info(
126 trx_purge_arr_remove_info(
145 trx_purge_arr_get_biggest(
170 if ((cell->
trx_no > pair_trx_no)
171 || ((cell->
trx_no == pair_trx_no)
172 && cell->
undo_no >= pair_undo_no)) {
174 pair_trx_no = cell->
trx_no;
184 *trx_no = pair_trx_no;
185 *undo_no = pair_undo_no;
194 trx_purge_graph_build(
void)
226 ut_ad(mutex_own(&kernel_mutex));
272 ut_ad(!mutex_own(&kernel_mutex));
284 mutex_enter(&kernel_mutex);
289 mutex_exit(&kernel_mutex);
337 if (undo->
state != TRX_UNDO_CACHED) {
345 if (UNIV_UNLIKELY(undo->
id >= TRX_RSEG_N_SLOTS)) {
347 "InnoDB: Error: undo->id is %lu\n",
355 rseg_header + TRX_RSEG_HISTORY_SIZE,
MLOG_4BYTES, mtr);
361 rseg_header + TRX_RSEG_HISTORY_SIZE,
366 rseg_header + TRX_RSEG_HISTORY,
391 mutex_enter(&kernel_mutex);
393 mutex_exit(&kernel_mutex);
406 trx_purge_free_segment(
410 ulint n_removed_logs)
421 ibool marked = FALSE;
428 mutex_enter(&(rseg->
mutex));
431 rseg->page_no, &mtr);
434 hdr_addr.
page, &mtr);
436 log_hdr = undo_page + hdr_addr.
boffset;
453 mutex_exit(&(rseg->
mutex));
470 flst_cut_end(rseg_hdr + TRX_RSEG_HISTORY,
473 mutex_enter(&kernel_mutex);
476 mutex_exit(&kernel_mutex);
492 ut_ad(hist_size >= seg_size);
497 ut_ad(rseg->curr_size >= seg_size);
499 rseg->curr_size -= seg_size;
501 mutex_exit(&(rseg->
mutex));
510 trx_purge_truncate_rseg_history(
525 ulint n_removed_logs = 0;
530 mutex_enter(&(rseg->
mutex));
533 rseg->page_no, &mtr);
540 mutex_exit(&(rseg->
mutex));
548 hdr_addr.
page, &mtr);
550 log_hdr = undo_page + hdr_addr.
boffset;
553 if (undo_trx_no >= limit_trx_no) {
554 if (undo_trx_no == limit_trx_no) {
561 mutex_enter(&kernel_mutex);
564 mutex_exit(&kernel_mutex);
566 flst_truncate_end(rseg_hdr + TRX_RSEG_HISTORY,
568 n_removed_logs, &mtr);
570 mutex_exit(&(rseg->
mutex));
587 mutex_exit(&(rseg->
mutex));
590 trx_purge_free_segment(rseg, hdr_addr, n_removed_logs);
594 mutex_exit(&(rseg->
mutex));
599 mutex_enter(&(rseg->
mutex));
602 rseg->page_no, &mtr);
604 hdr_addr = prev_hdr_addr;
614 trx_purge_truncate_history(
void)
621 trx_purge_arr_get_biggest(
624 if (limit_trx_no == 0) {
638 ut_ad(limit_trx_no <= purge_sys->view->low_limit_no);
644 trx_purge_truncate_rseg_history(
645 rseg, limit_trx_no, limit_undo_no);
654 trx_purge_truncate_if_arr_empty(
void)
661 trx_purge_truncate_history();
670 trx_purge_rseg_get_next_history_log(
683 mutex_enter(&(rseg->
mutex));
710 mutex_exit(&(rseg->
mutex));
713 mutex_enter(&kernel_mutex);
726 " InnoDB: Warning: purge reached the"
727 " head of the history list,\n"
728 "InnoDB: but its length is still"
729 " reported as %lu! Make a detailed bug\n"
730 "InnoDB: report, and submit it"
731 " to http://bugs.mysql.com\n",
735 mutex_exit(&kernel_mutex);
740 mutex_exit(&(rseg->
mutex));
747 prev_log_addr.
page, &mtr)
756 mutex_enter(&(rseg->
mutex));
763 rseg_queue.
rseg = rseg;
778 mutex_exit(&(rseg->
mutex));
787 trx_purge_get_rseg_with_min_trx_id(
794 mutex_enter(&purge_sys_instance->
bh_mutex);
805 mutex_exit(&purge_sys_instance->
bh_mutex);
807 purge_sys_instance->
rseg = rseg;
809 mutex_exit(&purge_sys_instance->
bh_mutex);
811 purge_sys_instance->
rseg = NULL;
813 return(ULINT_UNDEFINED);
816 ut_a(purge_sys_instance->
rseg != NULL);
818 mutex_enter(&purge_sys_instance->
rseg->
mutex);
826 zip_size = purge_sys_instance->
rseg->zip_size;
836 mutex_exit(&purge_sys_instance->
rseg->
mutex);
845 trx_purge_read_undo_rec(
852 ib_uint64_t undo_no = 0;
866 purge_sys_instance->
hdr_offset, RW_S_LATCH, &mtr);
868 if (undo_rec != NULL) {
877 purge_sys_instance->
offset = offset;
878 purge_sys_instance->
page_no = page_no;
891 trx_purge_choose_next_log(
void)
898 zip_size = trx_purge_get_rseg_with_min_trx_id(purge_sys);
902 trx_purge_read_undo_rec(purge_sys, zip_size);
914 trx_purge_get_next_rec(
947 trx_purge_choose_next_log();
949 return(&trx_purge_dummy_rec);
956 rec = undo_page + offset;
967 if (next_rec == NULL) {
978 if (type == TRX_UNDO_DEL_MARK_REC) {
989 if ((type == TRX_UNDO_UPD_EXIST_REC)
990 && !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
1002 trx_purge_choose_next_log();
1009 rec = undo_page + offset;
1017 if (undo_page != page) {
1048 trx_purge_truncate_if_arr_empty();
1052 trx_purge_choose_next_log();
1057 trx_purge_truncate_if_arr_empty();
1059 if (srv_print_thread_releases) {
1061 "Purge: No logs left in the"
1062 " history list; pages handled %lu\n",
1074 trx_purge_truncate_if_arr_empty();
1080 trx_purge_truncate_if_arr_empty();
1095 *cell = trx_purge_arr_store_info(
1103 undo_rec = trx_purge_get_next_rec(heap);
1116 trx_purge_arr_remove_info(cell);
1130 ulint old_pages_handled;
1138 mutex_enter(&kernel_mutex);
1149 srv_dml_needed_delay = 0;
1154 if (srv_max_purge_lag > 0
1157 / srv_max_purge_lag;
1158 if (ratio > ULINT_MAX / 10000) {
1160 srv_dml_needed_delay = ULINT_MAX;
1161 }
else if (ratio > 1) {
1166 srv_dml_needed_delay = (ulint) ((ratio - .5) * 10000);
1173 mutex_exit(&kernel_mutex);
1184 mutex_enter(&kernel_mutex);
1190 mutex_exit(&kernel_mutex);
1192 if (srv_print_thread_releases) {
1194 fputs(
"Starting purge\n", stderr);
1199 if (srv_print_thread_releases) {
1202 "Purge ends; pages handled %lu\n",
1216 fprintf(stderr,
"InnoDB: Purge system view:\n");
1219 fprintf(stderr,
"InnoDB: Purge trx n:o " TRX_ID_FMT
1224 "InnoDB: Purge next stored %lu, page_no %lu, offset %lu,\n"
1225 "InnoDB: Purge hdr_page_no %lu, hdr_offset %lu\n",