#include "trx0purge.h"#include "fsp0fsp.h"#include "mach0data.h"#include "trx0rseg.h"#include "trx0trx.h"#include "trx0roll.h"#include "read0read.h"#include "fut0fut.h"#include "que0que.h"#include "row0purge.h"#include "row0upd.h"#include "trx0rec.h"#include "srv0que.h"#include "os0thread.h"Include dependency graph for trx0purge.c:

Go to the source code of this file.
| ulint trx_purge | ( | void | ) |
Definition at line 1035 of file trx0purge.c.
References trx_purge_struct::handle_limit, trx_purge_struct::heap, kernel_mutex, trx_purge_struct::latch, mem_heap_empty(), trx_purge_struct::mutex, mutex_enter, mutex_exit(), trx_struct::n_active_thrs, trx_purge_struct::n_pages_handled, NULL, purge_sys, que_fork_start_command(), que_run_threads(), trx_purge_struct::query, read_view_close(), read_view_oldest_copy_or_open_new(), trx_sys_struct::rseg_history_len, rw_lock_x_lock, rw_lock_x_unlock, srv_dml_needed_delay, srv_max_purge_lag, srv_print_thread_releases, trx_purge_struct::state, trx_purge_struct::trx, TRX_PURGE_ON, trx_sys, ut_ad, ut_dulint_create(), ut_error, UT_LIST_GET_LAST, and trx_purge_struct::view.
Referenced by srv_master_thread().
01037 : number of undo log pages handled in 01038 the batch */ 01039 { 01040 que_thr_t* thr; 01041 /* que_thr_t* thr2; */ 01042 ulint old_pages_handled; 01043 01044 mutex_enter(&(purge_sys->mutex)); 01045 01046 if (purge_sys->trx->n_active_thrs > 0) { 01047 01048 mutex_exit(&(purge_sys->mutex)); 01049 01050 /* Should not happen */ 01051 01052 ut_error; 01053 01054 return(0); 01055 } 01056 01057 rw_lock_x_lock(&(purge_sys->latch)); 01058 01059 mutex_enter(&kernel_mutex); 01060 01061 /* Close and free the old purge view */ 01062 01063 read_view_close(purge_sys->view); 01064 purge_sys->view = NULL; 01065 mem_heap_empty(purge_sys->heap); 01066 01067 /* Determine how much data manipulation language (DML) statements 01068 need to be delayed in order to reduce the lagging of the purge 01069 thread. */ 01070 srv_dml_needed_delay = 0; /* in microseconds; default: no delay */ 01071 01072 /* If we cannot advance the 'purge view' because of an old 01073 'consistent read view', then the DML statements cannot be delayed. 01074 Also, srv_max_purge_lag <= 0 means 'infinity'. */ 01075 if (srv_max_purge_lag > 0 01076 && !UT_LIST_GET_LAST(trx_sys->view_list)) { 01077 float ratio = (float) trx_sys->rseg_history_len 01078 / srv_max_purge_lag; 01079 if (ratio > ULINT_MAX / 10000) { 01080 /* Avoid overflow: maximum delay is 4295 seconds */ 01081 srv_dml_needed_delay = ULINT_MAX; 01082 } else if (ratio > 1) { 01083 /* If the history list length exceeds the 01084 innodb_max_purge_lag, the 01085 data manipulation statements are delayed 01086 by at least 5000 microseconds. */ 01087 srv_dml_needed_delay = (ulint) ((ratio - .5) * 10000); 01088 } 01089 } 01090 01091 purge_sys->view = read_view_oldest_copy_or_open_new( 01092 ut_dulint_create(0, 0), 01093 purge_sys->heap); 01094 mutex_exit(&kernel_mutex); 01095 01096 rw_lock_x_unlock(&(purge_sys->latch)); 01097 01098 purge_sys->state = TRX_PURGE_ON; 01099 01100 /* Handle at most 20 undo log pages in one purge batch */ 01101 01102 purge_sys->handle_limit = purge_sys->n_pages_handled + 20; 01103 01104 old_pages_handled = purge_sys->n_pages_handled; 01105 01106 mutex_exit(&(purge_sys->mutex)); 01107 01108 mutex_enter(&kernel_mutex); 01109 01110 thr = que_fork_start_command(purge_sys->query); 01111 01112 ut_ad(thr); 01113 01114 /* thr2 = que_fork_start_command(purge_sys->query); 01115 01116 ut_ad(thr2); */ 01117 01118 01119 mutex_exit(&kernel_mutex); 01120 01121 /* srv_que_task_enqueue(thr2); */ 01122 01123 if (srv_print_thread_releases) { 01124 01125 fputs("Starting purge\n", stderr); 01126 } 01127 01128 que_run_threads(thr); 01129 01130 if (srv_print_thread_releases) { 01131 01132 fprintf(stderr, 01133 "Purge ends; pages handled %lu\n", 01134 (ulong) purge_sys->n_pages_handled); 01135 } 01136 01137 return(purge_sys->n_pages_handled - old_pages_handled); 01138 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 243 of file trx0purge.c.
References trx_undo_struct::del_marks, FALSE, FIL_NULL, flst_add_first(), flst_get_len(), trx_undo_struct::hdr_offset, trx_undo_struct::hdr_page_no, trx_undo_struct::id, kernel_mutex, trx_rseg_struct::last_del_marks, trx_rseg_struct::last_offset, trx_rseg_struct::last_page_no, trx_rseg_struct::last_trx_no, MLOG_2BYTES, MLOG_4BYTES, mlog_write_dulint(), mlog_write_ulint(), mtr_read_ulint(), trx_rseg_struct::mutex, mutex_enter, mutex_exit(), trx_struct::no, trx_rseg_struct::page_no, trx_undo_struct::rseg, trx_sys_struct::rseg_history_len, trx_undo_struct::size, trx_rseg_struct::space, trx_undo_struct::state, TRX_RSEG_HISTORY, TRX_RSEG_HISTORY_SIZE, TRX_RSEG_N_SLOTS, trx_rsegf_get(), trx_rsegf_set_nth_undo(), trx_sys, TRX_UNDO_CACHED, TRX_UNDO_DEL_MARKS, TRX_UNDO_HISTORY_NODE, TRX_UNDO_PAGE_HDR, TRX_UNDO_PAGE_LIST, TRX_UNDO_SEG_HDR, TRX_UNDO_TRX_NO, trx_struct::update_undo, ut_ad, and ut_error.
Referenced by trx_undo_update_cleanup().
00245 : transaction */ 00246 page_t* undo_page, /* in: update undo log header page, 00247 x-latched */ 00248 mtr_t* mtr) /* in: mtr */ 00249 { 00250 trx_undo_t* undo; 00251 trx_rseg_t* rseg; 00252 trx_rsegf_t* rseg_header; 00253 trx_usegf_t* seg_header; 00254 trx_ulogf_t* undo_header; 00255 trx_upagef_t* page_header; 00256 ulint hist_size; 00257 00258 undo = trx->update_undo; 00259 00260 ut_ad(undo); 00261 00262 rseg = undo->rseg; 00263 #ifdef UNIV_SYNC_DEBUG 00264 ut_ad(mutex_own(&(rseg->mutex))); 00265 #endif /* UNIV_SYNC_DEBUG */ 00266 00267 rseg_header = trx_rsegf_get(rseg->space, rseg->page_no, mtr); 00268 00269 undo_header = undo_page + undo->hdr_offset; 00270 seg_header = undo_page + TRX_UNDO_SEG_HDR; 00271 page_header = undo_page + TRX_UNDO_PAGE_HDR; 00272 00273 if (undo->state != TRX_UNDO_CACHED) { 00274 /* The undo log segment will not be reused */ 00275 00276 if (undo->id >= TRX_RSEG_N_SLOTS) { 00277 fprintf(stderr, 00278 "InnoDB: Error: undo->id is %lu\n", (ulong) undo->id); 00279 ut_error; 00280 } 00281 00282 trx_rsegf_set_nth_undo(rseg_header, undo->id, FIL_NULL, mtr); 00283 00284 hist_size = mtr_read_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE, 00285 MLOG_4BYTES, mtr); 00286 ut_ad(undo->size == 00287 flst_get_len(seg_header + TRX_UNDO_PAGE_LIST, mtr)); 00288 00289 mlog_write_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE, 00290 hist_size + undo->size, MLOG_4BYTES, mtr); 00291 } 00292 00293 /* Add the log as the first in the history list */ 00294 flst_add_first(rseg_header + TRX_RSEG_HISTORY, 00295 undo_header + TRX_UNDO_HISTORY_NODE, mtr); 00296 mutex_enter(&kernel_mutex); 00297 trx_sys->rseg_history_len++; 00298 mutex_exit(&kernel_mutex); 00299 00300 /* Write the trx number to the undo log header */ 00301 mlog_write_dulint(undo_header + TRX_UNDO_TRX_NO, trx->no, mtr); 00302 /* Write information about delete markings to the undo log header */ 00303 00304 if (!undo->del_marks) { 00305 mlog_write_ulint(undo_header + TRX_UNDO_DEL_MARKS, FALSE, 00306 MLOG_2BYTES, mtr); 00307 } 00308 00309 if (rseg->last_page_no == FIL_NULL) { 00310 00311 rseg->last_page_no = undo->hdr_page_no; 00312 rseg->last_offset = undo->hdr_offset; 00313 rseg->last_trx_no = trx->no; 00314 rseg->last_del_marks = undo->del_marks; 00315 } 00316 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void trx_purge_arr_get_biggest | ( | trx_undo_arr_t * | arr, | |
| dulint * | trx_no, | |||
| dulint * | undo_no | |||
| ) | [static] |
Definition at line 117 of file trx0purge.c.
References trx_undo_inf_struct::in_use, n, trx_undo_arr_struct::n_used, trx_undo_inf_struct::trx_no, trx_undo_arr_get_nth_info(), trx_undo_inf_struct::undo_no, ut_dulint_cmp(), and ut_dulint_zero.
Referenced by trx_purge_truncate_history().
00119 : purge array */ 00120 dulint* trx_no, /* out: transaction number: ut_dulint_zero 00121 if array is empty */ 00122 dulint* undo_no)/* out: undo number */ 00123 { 00124 trx_undo_inf_t* cell; 00125 dulint pair_trx_no; 00126 dulint pair_undo_no; 00127 int trx_cmp; 00128 ulint n_used; 00129 ulint i; 00130 ulint n; 00131 00132 n = 0; 00133 n_used = arr->n_used; 00134 pair_trx_no = ut_dulint_zero; 00135 pair_undo_no = ut_dulint_zero; 00136 00137 for (i = 0;; i++) { 00138 cell = trx_undo_arr_get_nth_info(arr, i); 00139 00140 if (cell->in_use) { 00141 n++; 00142 trx_cmp = ut_dulint_cmp(cell->trx_no, pair_trx_no); 00143 00144 if ((trx_cmp > 0) 00145 || ((trx_cmp == 0) 00146 && (ut_dulint_cmp(cell->undo_no, 00147 pair_undo_no) >= 0))) { 00148 00149 pair_trx_no = cell->trx_no; 00150 pair_undo_no = cell->undo_no; 00151 } 00152 } 00153 00154 if (n == n_used) { 00155 *trx_no = pair_trx_no; 00156 *undo_no = pair_undo_no; 00157 00158 return; 00159 } 00160 } 00161 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE void trx_purge_arr_remove_info | ( | trx_undo_inf_t * | cell | ) |
Definition at line 98 of file trx0purge.c.
References trx_purge_struct::arr, FALSE, trx_undo_inf_struct::in_use, trx_undo_arr_struct::n_used, purge_sys, and ut_ad.
Referenced by trx_purge_rec_release().
00100 : pointer to the storage cell */ 00101 { 00102 trx_undo_arr_t* arr; 00103 00104 arr = purge_sys->arr; 00105 00106 cell->in_use = FALSE; 00107 00108 ut_ad(arr->n_used > 0); 00109 00110 arr->n_used--; 00111 }
Here is the caller graph for this function:

| static trx_undo_inf_t* trx_purge_arr_store_info | ( | dulint | trx_no, | |
| dulint | undo_no | |||
| ) | [static] |
Definition at line 66 of file trx0purge.c.
References trx_purge_struct::arr, trx_undo_inf_struct::in_use, trx_undo_arr_struct::n_used, purge_sys, TRUE, trx_undo_inf_struct::trx_no, trx_undo_arr_get_nth_info(), and trx_undo_inf_struct::undo_no.
Referenced by trx_purge_fetch_next_rec().
00068 : pointer to the storage cell */ 00069 dulint trx_no, /* in: transaction number */ 00070 dulint undo_no)/* in: undo number */ 00071 { 00072 trx_undo_inf_t* cell; 00073 trx_undo_arr_t* arr; 00074 ulint i; 00075 00076 arr = purge_sys->arr; 00077 00078 for (i = 0;; i++) { 00079 cell = trx_undo_arr_get_nth_info(arr, i); 00080 00081 if (!(cell->in_use)) { 00082 /* Not in use, we may store here */ 00083 cell->undo_no = undo_no; 00084 cell->trx_no = trx_no; 00085 cell->in_use = TRUE; 00086 00087 arr->n_used++; 00088 00089 return(cell); 00090 } 00091 } 00092 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void trx_purge_choose_next_log | ( | void | ) | [static] |
Definition at line 704 of file trx0purge.c.
References buf_frame_align(), buf_frame_get_page_no(), FALSE, FIL_NULL, trx_purge_struct::hdr_offset, trx_purge_struct::hdr_page_no, trx_rseg_struct::last_del_marks, trx_rseg_struct::last_offset, trx_rseg_struct::last_page_no, trx_rseg_struct::last_trx_no, mtr_commit(), mtr_start(), trx_rseg_struct::mutex, trx_purge_struct::mutex, mutex_enter, mutex_exit(), trx_purge_struct::next_stored, NULL, trx_purge_struct::offset, offset, trx_purge_struct::page_no, purge_sys, trx_purge_struct::purge_trx_no, trx_purge_struct::purge_undo_no, trx_purge_struct::rseg, RW_S_LATCH, trx_rseg_struct::space, TRUE, trx_purge_dummy_rec, trx_sys, trx_undo_get_first_rec(), trx_undo_rec_get_undo_no(), ut_a, ut_ad, ut_dulint_cmp(), ut_dulint_max, ut_dulint_zero, UT_LIST_GET_FIRST, and UT_LIST_GET_NEXT.
Referenced by trx_purge_fetch_next_rec(), and trx_purge_get_next_rec().
00706 { 00707 trx_undo_rec_t* rec; 00708 trx_rseg_t* rseg; 00709 trx_rseg_t* min_rseg; 00710 dulint min_trx_no; 00711 ulint space = 0; /* remove warning (??? bug ???) */ 00712 ulint page_no = 0; /* remove warning (??? bug ???) */ 00713 ulint offset = 0; /* remove warning (??? bug ???) */ 00714 mtr_t mtr; 00715 00716 #ifdef UNIV_SYNC_DEBUG 00717 ut_ad(mutex_own(&(purge_sys->mutex))); 00718 #endif /* UNIV_SYNC_DEBUG */ 00719 ut_ad(purge_sys->next_stored == FALSE); 00720 00721 rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list); 00722 00723 min_trx_no = ut_dulint_max; 00724 00725 min_rseg = NULL; 00726 00727 while (rseg) { 00728 mutex_enter(&(rseg->mutex)); 00729 00730 if (rseg->last_page_no != FIL_NULL) { 00731 00732 if ((min_rseg == NULL) 00733 || (ut_dulint_cmp(min_trx_no, 00734 rseg->last_trx_no) > 0)) { 00735 00736 min_rseg = rseg; 00737 min_trx_no = rseg->last_trx_no; 00738 space = rseg->space; 00739 ut_a(space == 0); /* We assume in purge of 00740 externally stored fields 00741 that space id == 0 */ 00742 page_no = rseg->last_page_no; 00743 offset = rseg->last_offset; 00744 } 00745 } 00746 00747 mutex_exit(&(rseg->mutex)); 00748 00749 rseg = UT_LIST_GET_NEXT(rseg_list, rseg); 00750 } 00751 00752 if (min_rseg == NULL) { 00753 00754 return; 00755 } 00756 00757 mtr_start(&mtr); 00758 00759 if (!min_rseg->last_del_marks) { 00760 /* No need to purge this log */ 00761 00762 rec = &trx_purge_dummy_rec; 00763 } else { 00764 rec = trx_undo_get_first_rec(space, page_no, offset, 00765 RW_S_LATCH, &mtr); 00766 if (rec == NULL) { 00767 /* Undo log empty */ 00768 00769 rec = &trx_purge_dummy_rec; 00770 } 00771 } 00772 00773 purge_sys->next_stored = TRUE; 00774 purge_sys->rseg = min_rseg; 00775 00776 purge_sys->hdr_page_no = page_no; 00777 purge_sys->hdr_offset = offset; 00778 00779 purge_sys->purge_trx_no = min_trx_no; 00780 00781 if (rec == &trx_purge_dummy_rec) { 00782 00783 purge_sys->purge_undo_no = ut_dulint_zero; 00784 purge_sys->page_no = page_no; 00785 purge_sys->offset = 0; 00786 } else { 00787 purge_sys->purge_undo_no = trx_undo_rec_get_undo_no(rec); 00788 00789 purge_sys->page_no = buf_frame_get_page_no(rec); 00790 purge_sys->offset = rec - buf_frame_align(rec); 00791 } 00792 00793 mtr_commit(&mtr); 00794 }
Here is the call graph for this function:

Here is the caller graph for this function:

| trx_undo_rec_t* trx_purge_fetch_next_rec | ( | dulint * | roll_ptr, | |
| trx_undo_inf_t ** | cell, | |||
| mem_heap_t * | heap | |||
| ) |
Definition at line 922 of file trx0purge.c.
References FALSE, trx_purge_struct::handle_limit, read_view_struct::low_limit_no, trx_purge_struct::mutex, mutex_enter, mutex_exit(), trx_purge_struct::n_pages_handled, trx_purge_struct::next_stored, NULL, trx_purge_struct::offset, trx_purge_struct::page_no, purge_sys, trx_purge_struct::purge_trx_no, trx_purge_struct::purge_undo_no, trx_purge_struct::rseg, srv_print_thread_releases, trx_purge_struct::state, trx_purge_arr_store_info(), trx_purge_choose_next_log(), trx_purge_get_next_rec(), trx_purge_truncate_if_arr_empty(), TRX_STOP_PURGE, trx_undo_build_roll_ptr(), ut_ad, ut_dulint_cmp(), and trx_purge_struct::view.
Referenced by row_purge().
00924 : copy of an undo log record or 00925 pointer to the dummy undo log record 00926 &trx_purge_dummy_rec, if the whole undo log 00927 can skipped in purge; NULL if none left */ 00928 dulint* roll_ptr,/* out: roll pointer to undo record */ 00929 trx_undo_inf_t** cell, /* out: storage cell for the record in the 00930 purge array */ 00931 mem_heap_t* heap) /* in: memory heap where copied */ 00932 { 00933 trx_undo_rec_t* undo_rec; 00934 00935 mutex_enter(&(purge_sys->mutex)); 00936 00937 if (purge_sys->state == TRX_STOP_PURGE) { 00938 trx_purge_truncate_if_arr_empty(); 00939 00940 mutex_exit(&(purge_sys->mutex)); 00941 00942 return(NULL); 00943 } 00944 00945 if (!purge_sys->next_stored) { 00946 trx_purge_choose_next_log(); 00947 00948 if (!purge_sys->next_stored) { 00949 purge_sys->state = TRX_STOP_PURGE; 00950 00951 trx_purge_truncate_if_arr_empty(); 00952 00953 if (srv_print_thread_releases) { 00954 fprintf(stderr, 00955 "Purge: No logs left in the history list; pages handled %lu\n", 00956 (ulong) purge_sys->n_pages_handled); 00957 } 00958 00959 mutex_exit(&(purge_sys->mutex)); 00960 00961 return(NULL); 00962 } 00963 } 00964 00965 if (purge_sys->n_pages_handled >= purge_sys->handle_limit) { 00966 00967 purge_sys->state = TRX_STOP_PURGE; 00968 00969 trx_purge_truncate_if_arr_empty(); 00970 00971 mutex_exit(&(purge_sys->mutex)); 00972 00973 return(NULL); 00974 } 00975 00976 if (ut_dulint_cmp(purge_sys->purge_trx_no, 00977 purge_sys->view->low_limit_no) >= 0) { 00978 purge_sys->state = TRX_STOP_PURGE; 00979 00980 trx_purge_truncate_if_arr_empty(); 00981 00982 mutex_exit(&(purge_sys->mutex)); 00983 00984 return(NULL); 00985 } 00986 00987 /* fprintf(stderr, "Thread %lu purging trx %lu undo record %lu\n", 00988 os_thread_get_curr_id(), 00989 ut_dulint_get_low(purge_sys->purge_trx_no), 00990 ut_dulint_get_low(purge_sys->purge_undo_no)); */ 00991 00992 *roll_ptr = trx_undo_build_roll_ptr(FALSE, (purge_sys->rseg)->id, 00993 purge_sys->page_no, 00994 purge_sys->offset); 00995 00996 *cell = trx_purge_arr_store_info(purge_sys->purge_trx_no, 00997 purge_sys->purge_undo_no); 00998 00999 ut_ad(ut_dulint_cmp(purge_sys->purge_trx_no, 01000 (purge_sys->view)->low_limit_no) < 0); 01001 01002 /* The following call will advance the stored values of purge_trx_no 01003 and purge_undo_no, therefore we had to store them first */ 01004 01005 undo_rec = trx_purge_get_next_rec(heap); 01006 01007 mutex_exit(&(purge_sys->mutex)); 01008 01009 return(undo_rec); 01010 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void trx_purge_free_segment | ( | trx_rseg_t * | rseg, | |
| fil_addr_t | hdr_addr, | |||
| ulint | n_removed_logs | |||
| ) | [static] |
Definition at line 323 of file trx0purge.c.
References fil_addr_struct::boffset, trx_rseg_struct::curr_size, FALSE, flst_cut_end(), flst_get_len(), fseg_free_step(), fseg_free_step_not_header(), kernel_mutex, MLOG_2BYTES, MLOG_4BYTES, mlog_write_ulint(), mtr_commit(), mtr_read_ulint(), mtr_start(), trx_rseg_struct::mutex, trx_purge_struct::mutex, mutex_enter, mutex_exit(), fil_addr_struct::page, trx_rseg_struct::page_no, page_t, purge_sys, trx_sys_struct::rseg_history_len, trx_rseg_struct::space, TRUE, TRX_RSEG_HISTORY, TRX_RSEG_HISTORY_SIZE, trx_rsegf_get(), trx_sys, TRX_UNDO_DEL_MARKS, TRX_UNDO_FSEG_HEADER, TRX_UNDO_HISTORY_NODE, trx_undo_page_get(), TRX_UNDO_PAGE_LIST, TRX_UNDO_SEG_HDR, and ut_ad.
Referenced by trx_purge_truncate_rseg_history().
00325 : rollback segment */ 00326 fil_addr_t hdr_addr, /* in: the file address of log_hdr */ 00327 ulint n_removed_logs) /* in: count of how many undo logs we 00328 will cut off from the end of the 00329 history list */ 00330 { 00331 page_t* undo_page; 00332 trx_rsegf_t* rseg_hdr; 00333 trx_ulogf_t* log_hdr; 00334 trx_usegf_t* seg_hdr; 00335 ibool freed; 00336 ulint seg_size; 00337 ulint hist_size; 00338 ibool marked = FALSE; 00339 mtr_t mtr; 00340 00341 /* fputs("Freeing an update undo log segment\n", stderr); */ 00342 00343 #ifdef UNIV_SYNC_DEBUG 00344 ut_ad(mutex_own(&(purge_sys->mutex))); 00345 #endif /* UNIV_SYNC_DEBUG */ 00346 loop: 00347 mtr_start(&mtr); 00348 mutex_enter(&(rseg->mutex)); 00349 00350 rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr); 00351 00352 undo_page = trx_undo_page_get(rseg->space, hdr_addr.page, &mtr); 00353 seg_hdr = undo_page + TRX_UNDO_SEG_HDR; 00354 log_hdr = undo_page + hdr_addr.boffset; 00355 00356 /* Mark the last undo log totally purged, so that if the system 00357 crashes, the tail of the undo log will not get accessed again. The 00358 list of pages in the undo log tail gets inconsistent during the 00359 freeing of the segment, and therefore purge should not try to access 00360 them again. */ 00361 00362 if (!marked) { 00363 mlog_write_ulint(log_hdr + TRX_UNDO_DEL_MARKS, FALSE, 00364 MLOG_2BYTES, &mtr); 00365 marked = TRUE; 00366 } 00367 00368 freed = fseg_free_step_not_header(seg_hdr + TRX_UNDO_FSEG_HEADER, 00369 &mtr); 00370 if (!freed) { 00371 mutex_exit(&(rseg->mutex)); 00372 mtr_commit(&mtr); 00373 00374 goto loop; 00375 } 00376 00377 /* The page list may now be inconsistent, but the length field 00378 stored in the list base node tells us how big it was before we 00379 started the freeing. */ 00380 00381 seg_size = flst_get_len(seg_hdr + TRX_UNDO_PAGE_LIST, &mtr); 00382 00383 /* We may free the undo log segment header page; it must be freed 00384 within the same mtr as the undo log header is removed from the 00385 history list: otherwise, in case of a database crash, the segment 00386 could become inaccessible garbage in the file space. */ 00387 00388 flst_cut_end(rseg_hdr + TRX_RSEG_HISTORY, 00389 log_hdr + TRX_UNDO_HISTORY_NODE, n_removed_logs, &mtr); 00390 00391 mutex_enter(&kernel_mutex); 00392 ut_ad(trx_sys->rseg_history_len >= n_removed_logs); 00393 trx_sys->rseg_history_len -= n_removed_logs; 00394 mutex_exit(&kernel_mutex); 00395 00396 freed = FALSE; 00397 00398 while (!freed) { 00399 /* Here we assume that a file segment with just the header 00400 page can be freed in a few steps, so that the buffer pool 00401 is not flooded with bufferfixed pages: see the note in 00402 fsp0fsp.c. */ 00403 00404 freed = fseg_free_step(seg_hdr + TRX_UNDO_FSEG_HEADER, 00405 &mtr); 00406 } 00407 00408 hist_size = mtr_read_ulint(rseg_hdr + TRX_RSEG_HISTORY_SIZE, 00409 MLOG_4BYTES, &mtr); 00410 ut_ad(hist_size >= seg_size); 00411 00412 mlog_write_ulint(rseg_hdr + TRX_RSEG_HISTORY_SIZE, 00413 hist_size - seg_size, MLOG_4BYTES, &mtr); 00414 00415 ut_ad(rseg->curr_size >= seg_size); 00416 00417 rseg->curr_size -= seg_size; 00418 00419 mutex_exit(&(rseg->mutex)); 00420 00421 mtr_commit(&mtr); 00422 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static trx_undo_rec_t* trx_purge_get_next_rec | ( | mem_heap_t * | heap | ) | [static] |
Definition at line 800 of file trx0purge.c.
References buf_frame_align(), buf_frame_get_page_no(), trx_purge_struct::hdr_offset, trx_purge_struct::hdr_page_no, mtr_commit(), mtr_start(), trx_purge_struct::mutex, trx_purge_struct::n_pages_handled, trx_purge_struct::next_stored, NULL, trx_purge_struct::offset, offset, page, trx_purge_struct::page_no, page_t, purge_sys, trx_purge_struct::purge_undo_no, rec_copy(), trx_purge_struct::rseg, trx_rseg_struct::space, trx_purge_choose_next_log(), trx_purge_dummy_rec, trx_purge_rseg_get_next_history_log(), TRX_UNDO_DEL_MARK_REC, trx_undo_get_next_rec(), trx_undo_page_get_next_rec(), trx_undo_page_get_s_latched(), trx_undo_rec_copy(), trx_undo_rec_get_cmpl_info(), trx_undo_rec_get_extern_storage(), trx_undo_rec_get_type(), trx_undo_rec_get_undo_no(), TRX_UNDO_UPD_EXIST_REC, UPD_NODE_NO_ORD_CHANGE, and ut_ad.
Referenced by trx_purge_fetch_next_rec().
00802 : copy of an undo log record or 00803 pointer to the dummy undo log record */ 00804 mem_heap_t* heap) /* in: memory heap where copied */ 00805 { 00806 trx_undo_rec_t* rec; 00807 trx_undo_rec_t* rec_copy; 00808 trx_undo_rec_t* rec2; 00809 trx_undo_rec_t* next_rec; 00810 page_t* undo_page; 00811 page_t* page; 00812 ulint offset; 00813 ulint page_no; 00814 ulint space; 00815 ulint type; 00816 ulint cmpl_info; 00817 mtr_t mtr; 00818 00819 #ifdef UNIV_SYNC_DEBUG 00820 ut_ad(mutex_own(&(purge_sys->mutex))); 00821 #endif /* UNIV_SYNC_DEBUG */ 00822 ut_ad(purge_sys->next_stored); 00823 00824 space = purge_sys->rseg->space; 00825 page_no = purge_sys->page_no; 00826 offset = purge_sys->offset; 00827 00828 if (offset == 0) { 00829 /* It is the dummy undo log record, which means that there is 00830 no need to purge this undo log */ 00831 00832 trx_purge_rseg_get_next_history_log(purge_sys->rseg); 00833 00834 /* Look for the next undo log and record to purge */ 00835 00836 trx_purge_choose_next_log(); 00837 00838 return(&trx_purge_dummy_rec); 00839 } 00840 00841 mtr_start(&mtr); 00842 00843 undo_page = trx_undo_page_get_s_latched(space, page_no, &mtr); 00844 rec = undo_page + offset; 00845 00846 rec2 = rec; 00847 00848 for (;;) { 00849 /* Try first to find the next record which requires a purge 00850 operation from the same page of the same undo log */ 00851 00852 next_rec = trx_undo_page_get_next_rec(rec2, 00853 purge_sys->hdr_page_no, 00854 purge_sys->hdr_offset); 00855 if (next_rec == NULL) { 00856 rec2 = trx_undo_get_next_rec(rec2, 00857 purge_sys->hdr_page_no, 00858 purge_sys->hdr_offset, &mtr); 00859 break; 00860 } 00861 00862 rec2 = next_rec; 00863 00864 type = trx_undo_rec_get_type(rec2); 00865 00866 if (type == TRX_UNDO_DEL_MARK_REC) { 00867 00868 break; 00869 } 00870 00871 cmpl_info = trx_undo_rec_get_cmpl_info(rec2); 00872 00873 if (trx_undo_rec_get_extern_storage(rec2)) { 00874 break; 00875 } 00876 00877 if ((type == TRX_UNDO_UPD_EXIST_REC) 00878 && !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { 00879 break; 00880 } 00881 } 00882 00883 if (rec2 == NULL) { 00884 mtr_commit(&mtr); 00885 00886 trx_purge_rseg_get_next_history_log(purge_sys->rseg); 00887 00888 /* Look for the next undo log and record to purge */ 00889 00890 trx_purge_choose_next_log(); 00891 00892 mtr_start(&mtr); 00893 00894 undo_page = trx_undo_page_get_s_latched(space, page_no, &mtr); 00895 00896 rec = undo_page + offset; 00897 } else { 00898 page = buf_frame_align(rec2); 00899 00900 purge_sys->purge_undo_no = trx_undo_rec_get_undo_no(rec2); 00901 purge_sys->page_no = buf_frame_get_page_no(page); 00902 purge_sys->offset = rec2 - page; 00903 00904 if (undo_page != page) { 00905 /* We advance to a new page of the undo log: */ 00906 purge_sys->n_pages_handled++; 00907 } 00908 } 00909 00910 rec_copy = trx_undo_rec_copy(rec, heap); 00911 00912 mtr_commit(&mtr); 00913 00914 return(rec_copy); 00915 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static que_t* trx_purge_graph_build | ( | void | ) | [static] |
Definition at line 168 of file trx0purge.c.
References que_thr_struct::child, mem_heap_create, NULL, purge_sys, que_fork_create(), QUE_FORK_PURGE, que_thr_create(), row_purge_node_create(), trx_purge_struct::trx, and que_fork_struct::trx.
Referenced by trx_purge_sys_create().
00170 : the query graph */ 00171 { 00172 mem_heap_t* heap; 00173 que_fork_t* fork; 00174 que_thr_t* thr; 00175 /* que_thr_t* thr2; */ 00176 00177 heap = mem_heap_create(512); 00178 fork = que_fork_create(NULL, NULL, QUE_FORK_PURGE, heap); 00179 fork->trx = purge_sys->trx; 00180 00181 thr = que_thr_create(fork, heap); 00182 00183 thr->child = row_purge_node_create(thr, heap); 00184 00185 /* thr2 = que_thr_create(fork, fork, heap); 00186 00187 thr2->child = row_purge_node_create(fork, thr2, heap); */ 00188 00189 return(fork); 00190 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void trx_purge_rec_release | ( | trx_undo_inf_t * | cell | ) |
Definition at line 1016 of file trx0purge.c.
References trx_purge_struct::arr, trx_purge_struct::mutex, mutex_enter, mutex_exit(), purge_sys, and trx_purge_arr_remove_info().
Referenced by row_purge().
01018 : storage cell */ 01019 { 01020 trx_undo_arr_t* arr; 01021 01022 mutex_enter(&(purge_sys->mutex)); 01023 01024 arr = purge_sys->arr; 01025 01026 trx_purge_arr_remove_info(cell); 01027 01028 mutex_exit(&(purge_sys->mutex)); 01029 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void trx_purge_rseg_get_next_history_log | ( | trx_rseg_t * | rseg | ) | [static] |
Definition at line 601 of file trx0purge.c.
References fil_addr_struct::boffset, FALSE, FIL_NULL, flst_get_prev_addr(), kernel_mutex, trx_rseg_struct::last_del_marks, trx_rseg_struct::last_offset, trx_rseg_struct::last_page_no, trx_rseg_struct::last_trx_no, mach_read_from_2(), mach_read_from_8(), mtr_commit(), mtr_start(), trx_rseg_struct::mutex, trx_purge_struct::mutex, mutex_enter, mutex_exit(), trx_purge_struct::n_pages_handled, trx_purge_struct::next_stored, fil_addr_struct::page, page_t, purge_sys, trx_purge_struct::purge_trx_no, trx_purge_struct::purge_undo_no, trx_sys_struct::rseg_history_len, trx_rseg_struct::space, trx_purge_get_log_from_hist(), trx_sys, TRX_UNDO_DEL_MARKS, TRX_UNDO_HISTORY_NODE, trx_undo_page_get_s_latched(), TRX_UNDO_SEG_HDR, TRX_UNDO_TRX_NO, ut_a, ut_ad, ut_dulint_add(), ut_dulint_zero, and ut_print_timestamp().
Referenced by trx_purge_get_next_rec().
00603 : rollback segment */ 00604 { 00605 page_t* undo_page; 00606 trx_ulogf_t* log_hdr; 00607 trx_usegf_t* seg_hdr; 00608 fil_addr_t prev_log_addr; 00609 dulint trx_no; 00610 ibool del_marks; 00611 mtr_t mtr; 00612 00613 #ifdef UNIV_SYNC_DEBUG 00614 ut_ad(mutex_own(&(purge_sys->mutex))); 00615 #endif /* UNIV_SYNC_DEBUG */ 00616 00617 mutex_enter(&(rseg->mutex)); 00618 00619 ut_a(rseg->last_page_no != FIL_NULL); 00620 00621 purge_sys->purge_trx_no = ut_dulint_add(rseg->last_trx_no, 1); 00622 purge_sys->purge_undo_no = ut_dulint_zero; 00623 purge_sys->next_stored = FALSE; 00624 00625 mtr_start(&mtr); 00626 00627 undo_page = trx_undo_page_get_s_latched(rseg->space, 00628 rseg->last_page_no, &mtr); 00629 log_hdr = undo_page + rseg->last_offset; 00630 seg_hdr = undo_page + TRX_UNDO_SEG_HDR; 00631 00632 /* Increase the purge page count by one for every handled log */ 00633 00634 purge_sys->n_pages_handled++; 00635 00636 prev_log_addr = trx_purge_get_log_from_hist( 00637 flst_get_prev_addr(log_hdr + TRX_UNDO_HISTORY_NODE, 00638 &mtr)); 00639 if (prev_log_addr.page == FIL_NULL) { 00640 /* No logs left in the history list */ 00641 00642 rseg->last_page_no = FIL_NULL; 00643 00644 mutex_exit(&(rseg->mutex)); 00645 mtr_commit(&mtr); 00646 00647 mutex_enter(&kernel_mutex); 00648 00649 /* Add debug code to track history list corruption reported 00650 on the MySQL mailing list on Nov 9, 2004. The fut0lst.c 00651 file-based list was corrupt. The prev node pointer was 00652 FIL_NULL, even though the list length was over 8 million nodes! 00653 We assume that purge truncates the history list in moderate 00654 size pieces, and if we here reach the head of the list, the 00655 list cannot be longer than 20 000 undo logs now. */ 00656 00657 if (trx_sys->rseg_history_len > 20000) { 00658 ut_print_timestamp(stderr); 00659 fprintf(stderr, 00660 " InnoDB: Warning: purge reached the head of the history list,\n" 00661 "InnoDB: but its length is still reported as %lu! Make a detailed bug\n" 00662 "InnoDB: report, and post it to bugs.mysql.com\n", 00663 (ulong)trx_sys->rseg_history_len); 00664 } 00665 00666 mutex_exit(&kernel_mutex); 00667 00668 return; 00669 } 00670 00671 mutex_exit(&(rseg->mutex)); 00672 mtr_commit(&mtr); 00673 00674 /* Read the trx number and del marks from the previous log header */ 00675 mtr_start(&mtr); 00676 00677 log_hdr = trx_undo_page_get_s_latched(rseg->space, 00678 prev_log_addr.page, &mtr) 00679 + prev_log_addr.boffset; 00680 00681 trx_no = mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO); 00682 00683 del_marks = mach_read_from_2(log_hdr + TRX_UNDO_DEL_MARKS); 00684 00685 mtr_commit(&mtr); 00686 00687 mutex_enter(&(rseg->mutex)); 00688 00689 rseg->last_page_no = prev_log_addr.page; 00690 rseg->last_offset = prev_log_addr.boffset; 00691 rseg->last_trx_no = trx_no; 00692 rseg->last_del_marks = del_marks; 00693 00694 mutex_exit(&(rseg->mutex)); 00695 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void trx_purge_sys_create | ( | void | ) |
Definition at line 197 of file trx0purge.c.
References trx_purge_struct::arr, FALSE, trx_purge_struct::heap, kernel_mutex, trx_purge_struct::latch, mem_alloc, mem_heap_create, trx_purge_struct::mutex, mutex_create, trx_purge_struct::n_pages_handled, trx_purge_struct::next_stored, purge_sys, trx_purge_struct::purge_trx_no, trx_purge_struct::purge_undo_no, trx_purge_struct::query, read_view_oldest_copy_or_open_new(), rw_lock_create, trx_purge_struct::sess, sess_open(), trx_purge_struct::state, SYNC_PURGE_LATCH, SYNC_PURGE_SYS, sess_struct::trx, trx_purge_struct::trx, TRX_PURGE, trx_purge_graph_build(), trx_start_low(), TRX_STOP_PURGE, trx_undo_arr_create(), trx_struct::type, ut_a, ut_ad, ut_dulint_create(), ut_dulint_zero, and trx_purge_struct::view.
00199 { 00200 #ifdef UNIV_SYNC_DEBUG 00201 ut_ad(mutex_own(&kernel_mutex)); 00202 #endif /* UNIV_SYNC_DEBUG */ 00203 00204 purge_sys = mem_alloc(sizeof(trx_purge_t)); 00205 00206 purge_sys->state = TRX_STOP_PURGE; 00207 00208 purge_sys->n_pages_handled = 0; 00209 00210 purge_sys->purge_trx_no = ut_dulint_zero; 00211 purge_sys->purge_undo_no = ut_dulint_zero; 00212 purge_sys->next_stored = FALSE; 00213 00214 rw_lock_create(&purge_sys->latch, SYNC_PURGE_LATCH); 00215 00216 mutex_create(&purge_sys->mutex, SYNC_PURGE_SYS); 00217 00218 purge_sys->heap = mem_heap_create(256); 00219 00220 purge_sys->arr = trx_undo_arr_create(); 00221 00222 purge_sys->sess = sess_open(); 00223 00224 purge_sys->trx = purge_sys->sess->trx; 00225 00226 purge_sys->trx->type = TRX_PURGE; 00227 00228 ut_a(trx_start_low(purge_sys->trx, ULINT_UNDEFINED)); 00229 00230 purge_sys->query = trx_purge_graph_build(); 00231 00232 purge_sys->view = read_view_oldest_copy_or_open_new( 00233 ut_dulint_create(0,0), purge_sys->heap); 00234 }
Here is the call graph for this function:

| void trx_purge_sys_print | ( | void | ) |
Definition at line 1144 of file trx0purge.c.
References trx_purge_struct::hdr_offset, trx_purge_struct::hdr_page_no, trx_purge_struct::next_stored, trx_purge_struct::offset, trx_purge_struct::page_no, purge_sys, trx_purge_struct::purge_trx_no, trx_purge_struct::purge_undo_no, read_view_print(), ut_dulint_get_high(), ut_dulint_get_low(), and trx_purge_struct::view.
Referenced by trx_undo_prev_version_build().
01146 { 01147 fprintf(stderr, "InnoDB: Purge system view:\n"); 01148 read_view_print(purge_sys->view); 01149 01150 fprintf(stderr, "InnoDB: Purge trx n:o %lu %lu, undo n_o %lu %lu\n", 01151 (ulong) ut_dulint_get_high(purge_sys->purge_trx_no), 01152 (ulong) ut_dulint_get_low(purge_sys->purge_trx_no), 01153 (ulong) ut_dulint_get_high(purge_sys->purge_undo_no), 01154 (ulong) ut_dulint_get_low(purge_sys->purge_undo_no)); 01155 fprintf(stderr, 01156 "InnoDB: Purge next stored %lu, page_no %lu, offset %lu,\n" 01157 "InnoDB: Purge hdr_page_no %lu, hdr_offset %lu\n", 01158 (ulong) purge_sys->next_stored, 01159 (ulong) purge_sys->page_no, 01160 (ulong) purge_sys->offset, 01161 (ulong) purge_sys->hdr_page_no, 01162 (ulong) purge_sys->hdr_offset); 01163 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void trx_purge_truncate_history | ( | void | ) | [static] |
Definition at line 533 of file trx0purge.c.
References trx_purge_struct::arr, read_view_struct::low_limit_no, trx_purge_struct::mutex, purge_sys, trx_purge_struct::purge_trx_no, trx_purge_struct::purge_undo_no, trx_purge_arr_get_biggest(), trx_purge_truncate_rseg_history(), trx_sys, ut_ad, ut_dulint_cmp(), ut_dulint_zero, UT_LIST_GET_FIRST, UT_LIST_GET_NEXT, and trx_purge_struct::view.
Referenced by trx_purge_truncate_if_arr_empty().
00535 { 00536 trx_rseg_t* rseg; 00537 dulint limit_trx_no; 00538 dulint limit_undo_no; 00539 00540 #ifdef UNIV_SYNC_DEBUG 00541 ut_ad(mutex_own(&(purge_sys->mutex))); 00542 #endif /* UNIV_SYNC_DEBUG */ 00543 00544 trx_purge_arr_get_biggest(purge_sys->arr, &limit_trx_no, 00545 &limit_undo_no); 00546 00547 if (ut_dulint_cmp(limit_trx_no, ut_dulint_zero) == 0) { 00548 00549 limit_trx_no = purge_sys->purge_trx_no; 00550 limit_undo_no = purge_sys->purge_undo_no; 00551 } 00552 00553 /* We play safe and set the truncate limit at most to the purge view 00554 low_limit number, though this is not necessary */ 00555 00556 if (ut_dulint_cmp(limit_trx_no, purge_sys->view->low_limit_no) >= 0) { 00557 limit_trx_no = purge_sys->view->low_limit_no; 00558 limit_undo_no = ut_dulint_zero; 00559 } 00560 00561 ut_ad((ut_dulint_cmp(limit_trx_no, 00562 purge_sys->view->low_limit_no) <= 0)); 00563 00564 rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list); 00565 00566 while (rseg) { 00567 trx_purge_truncate_rseg_history(rseg, limit_trx_no, 00568 limit_undo_no); 00569 rseg = UT_LIST_GET_NEXT(rseg_list, rseg); 00570 } 00571 }
Here is the call graph for this function:

Here is the caller graph for this function:

| UNIV_INLINE ibool trx_purge_truncate_if_arr_empty | ( | void | ) |
Definition at line 578 of file trx0purge.c.
References trx_purge_struct::arr, FALSE, trx_purge_struct::mutex, trx_undo_arr_struct::n_used, purge_sys, TRUE, trx_purge_truncate_history(), and ut_ad.
Referenced by trx_purge_fetch_next_rec().
00580 : TRUE if array empty */ 00581 { 00582 #ifdef UNIV_SYNC_DEBUG 00583 ut_ad(mutex_own(&(purge_sys->mutex))); 00584 #endif /* UNIV_SYNC_DEBUG */ 00585 00586 if (purge_sys->arr->n_used == 0) { 00587 00588 trx_purge_truncate_history(); 00589 00590 return(TRUE); 00591 } 00592 00593 return(FALSE); 00594 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void trx_purge_truncate_rseg_history | ( | trx_rseg_t * | rseg, | |
| dulint | limit_trx_no, | |||
| dulint | limit_undo_no | |||
| ) | [static] |
Definition at line 428 of file trx0purge.c.
References fil_addr_struct::boffset, cmp, FIL_NULL, flst_get_last(), flst_get_prev_addr(), flst_truncate_end(), kernel_mutex, mach_read_from_2(), mach_read_from_8(), mtr_commit(), mtr_start(), trx_rseg_struct::mutex, trx_purge_struct::mutex, mutex_enter, mutex_exit(), fil_addr_struct::page, trx_rseg_struct::page_no, page_t, purge_sys, trx_sys_struct::rseg_history_len, trx_rseg_struct::space, trx_purge_free_segment(), trx_purge_get_log_from_hist(), TRX_RSEG_HISTORY, trx_rsegf_get(), trx_sys, TRX_UNDO_HISTORY_NODE, TRX_UNDO_NEXT_LOG, trx_undo_page_get(), TRX_UNDO_SEG_HDR, TRX_UNDO_STATE, TRX_UNDO_TO_PURGE, trx_undo_truncate_start(), TRX_UNDO_TRX_NO, ut_a, ut_ad, and ut_dulint_cmp().
Referenced by trx_purge_truncate_history().
00430 : rollback segment */ 00431 dulint limit_trx_no, /* in: remove update undo logs whose 00432 trx number is < limit_trx_no */ 00433 dulint limit_undo_no) /* in: if transaction number is equal 00434 to limit_trx_no, truncate undo records 00435 with undo number < limit_undo_no */ 00436 { 00437 fil_addr_t hdr_addr; 00438 fil_addr_t prev_hdr_addr; 00439 trx_rsegf_t* rseg_hdr; 00440 page_t* undo_page; 00441 trx_ulogf_t* log_hdr; 00442 trx_usegf_t* seg_hdr; 00443 int cmp; 00444 ulint n_removed_logs = 0; 00445 mtr_t mtr; 00446 00447 #ifdef UNIV_SYNC_DEBUG 00448 ut_ad(mutex_own(&(purge_sys->mutex))); 00449 #endif /* UNIV_SYNC_DEBUG */ 00450 00451 mtr_start(&mtr); 00452 mutex_enter(&(rseg->mutex)); 00453 00454 rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr); 00455 00456 hdr_addr = trx_purge_get_log_from_hist( 00457 flst_get_last(rseg_hdr + TRX_RSEG_HISTORY, &mtr)); 00458 loop: 00459 if (hdr_addr.page == FIL_NULL) { 00460 00461 mutex_exit(&(rseg->mutex)); 00462 00463 mtr_commit(&mtr); 00464 00465 return; 00466 } 00467 00468 undo_page = trx_undo_page_get(rseg->space, hdr_addr.page, &mtr); 00469 00470 log_hdr = undo_page + hdr_addr.boffset; 00471 00472 cmp = ut_dulint_cmp(mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO), 00473 limit_trx_no); 00474 if (cmp == 0) { 00475 trx_undo_truncate_start(rseg, rseg->space, hdr_addr.page, 00476 hdr_addr.boffset, limit_undo_no); 00477 } 00478 00479 if (cmp >= 0) { 00480 mutex_enter(&kernel_mutex); 00481 ut_a(trx_sys->rseg_history_len >= n_removed_logs); 00482 trx_sys->rseg_history_len -= n_removed_logs; 00483 mutex_exit(&kernel_mutex); 00484 00485 flst_truncate_end(rseg_hdr + TRX_RSEG_HISTORY, 00486 log_hdr + TRX_UNDO_HISTORY_NODE, 00487 n_removed_logs, &mtr); 00488 00489 mutex_exit(&(rseg->mutex)); 00490 mtr_commit(&mtr); 00491 00492 return; 00493 } 00494 00495 prev_hdr_addr = trx_purge_get_log_from_hist( 00496 flst_get_prev_addr(log_hdr + TRX_UNDO_HISTORY_NODE, 00497 &mtr)); 00498 n_removed_logs++; 00499 00500 seg_hdr = undo_page + TRX_UNDO_SEG_HDR; 00501 00502 if ((mach_read_from_2(seg_hdr + TRX_UNDO_STATE) == TRX_UNDO_TO_PURGE) 00503 && (mach_read_from_2(log_hdr + TRX_UNDO_NEXT_LOG) == 0)) { 00504 00505 /* We can free the whole log segment */ 00506 00507 mutex_exit(&(rseg->mutex)); 00508 mtr_commit(&mtr); 00509 00510 trx_purge_free_segment(rseg, hdr_addr, n_removed_logs); 00511 00512 n_removed_logs = 0; 00513 } else { 00514 mutex_exit(&(rseg->mutex)); 00515 mtr_commit(&mtr); 00516 } 00517 00518 mtr_start(&mtr); 00519 mutex_enter(&(rseg->mutex)); 00520 00521 rseg_hdr = trx_rsegf_get(rseg->space, rseg->page_no, &mtr); 00522 00523 hdr_addr = prev_hdr_addr; 00524 00525 goto loop; 00526 }
Here is the call graph for this function:

Here is the caller graph for this function:

| ibool trx_purge_update_undo_must_exist | ( | dulint | trx_id | ) |
Definition at line 41 of file trx0purge.c.
References FALSE, trx_purge_struct::latch, purge_sys, read_view_sees_trx_id(), RW_LOCK_SHARED, TRUE, ut_ad, and trx_purge_struct::view.
Referenced by row_vers_must_preserve_del_marked(), and trx_undo_get_undo_rec().
00043 : TRUE if is sure that it is preserved, also 00044 if the function returns FALSE, it is possible that 00045 the undo log still exists in the system */ 00046 dulint trx_id) /* in: transaction id */ 00047 { 00048 #ifdef UNIV_SYNC_DEBUG 00049 ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED)); 00050 #endif /* UNIV_SYNC_DEBUG */ 00051 00052 if (!read_view_sees_trx_id(purge_sys->view, trx_id)) { 00053 00054 return(TRUE); 00055 } 00056 00057 return(FALSE); 00058 }
Here is the call graph for this function:

Here is the caller graph for this function:

| trx_purge_t* purge_sys = NULL |
Definition at line 30 of file trx0purge.c.
Referenced by lock_print_info_summary(), row_vers_build_for_consistent_read(), row_vers_build_for_semi_consistent_read(), row_vers_impl_x_locked_off_kernel(), row_vers_must_preserve_del_marked(), row_vers_old_has_index_entry(), trx_purge(), trx_purge_arr_remove_info(), trx_purge_arr_store_info(), trx_purge_choose_next_log(), trx_purge_fetch_next_rec(), trx_purge_free_segment(), trx_purge_get_next_rec(), trx_purge_graph_build(), trx_purge_rec_release(), trx_purge_rseg_get_next_history_log(), trx_purge_sys_create(), trx_purge_sys_print(), trx_purge_truncate_history(), trx_purge_truncate_if_arr_empty(), trx_purge_truncate_rseg_history(), trx_purge_update_undo_must_exist(), trx_undo_get_undo_rec(), and trx_undo_prev_version_build().
Definition at line 34 of file trx0purge.c.
Referenced by row_purge(), trx_purge_choose_next_log(), and trx_purge_get_next_rec().
1.4.7

