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));
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);
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();
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",
UNIV_INLINE ibool read_view_sees_trx_id(const read_view_t *view, trx_id_t trx_id)
#define rw_lock_create(K, L, level)
#define UT_LIST_GET_NEXT(NAME, N)
UNIV_INLINE fil_addr_t flst_get_last(const flst_base_node_t *base, mtr_t *mtr)
UNIV_INLINE ulint trx_undo_rec_get_type(const trx_undo_rec_t *undo_rec)
UNIV_INLINE fil_addr_t flst_get_prev_addr(const flst_node_t *node, mtr_t *mtr)
UNIV_INLINE page_t * page_align(const void *ptr) __attribute__((const ))
UNIV_INLINE ulint page_get_page_no(const page_t *page)
UNIV_INTERN void read_view_close(read_view_t *view)
UNIV_INTERN void flst_truncate_end(flst_base_node_t *base, flst_node_t *node2, ulint n_nodes, mtr_t *mtr)
UNIV_INTERN void trx_purge_sys_print(void)
UNIV_INTERN void que_run_threads(que_thr_t *thr)
UNIV_INTERN void mlog_write_ulint(byte *ptr, ulint val, byte type, mtr_t *mtr)
#define TRX_UNDO_NEXT_LOG
UNIV_INTERN void trx_undo_truncate_start(trx_rseg_t *rseg, ulint space, ulint hdr_page_no, ulint hdr_offset, undo_no_t limit)
UNIV_INTERN ulint trx_purge(ulint limit)
UNIV_INLINE rec_t * rec_copy(void *buf, const rec_t *rec, const ulint *offsets)
#define mem_heap_free(heap)
UNIV_INLINE ulint trx_undo_rec_get_cmpl_info(const trx_undo_rec_t *undo_rec)
UNIV_INTERN void sess_close(sess_t *sess)
#define TRX_UNDO_FSEG_HEADER
UNIV_INTERN void trx_purge_sys_create(ib_bh_t *ib_bh)
UNIV_INTERN void trx_purge_rec_release(trx_undo_inf_t *cell)
trx_undo_rec_t trx_purge_dummy_rec
UNIV_INTERN void os_thread_yield(void)
UNIV_INTERN void mtr_commit(mtr_t *mtr) __attribute__((nonnull))
UNIV_INLINE ibool ib_bh_is_empty(const ib_bh_t *ib_bh)
UNIV_INTERN ulint mtr_read_ulint(const byte *ptr, ulint type, mtr_t *mtr)
UNIV_INLINE roll_ptr_t trx_undo_build_roll_ptr(ibool is_insert, ulint rseg_id, ulint page_no, ulint offset)
UNIV_INLINE fil_addr_t trx_purge_get_log_from_hist(fil_addr_t node_addr)
UNIV_INLINE page_t * trx_undo_page_get(ulint space, ulint zip_size, ulint page_no, mtr_t *mtr)
UNIV_INLINE trx_undo_inf_t * trx_undo_arr_get_nth_info(trx_undo_arr_t *arr, ulint n)
UNIV_INTERN void mlog_write_ull(byte *ptr, ib_uint64_t val, mtr_t *mtr)
UNIV_INTERN void que_graph_free(que_t *graph)
UNIV_INTERN read_view_t * read_view_oldest_copy_or_open_new(trx_id_t cr_trx_id, mem_heap_t *heap)
UNIV_INTERN void * ib_bh_push(ib_bh_t *ib_bh, const void *elem)
UNIV_INLINE ulint page_offset(const void *ptr) __attribute__((const ))
UNIV_INLINE trx_rsegf_t * trx_rsegf_get(ulint space, ulint zip_size, ulint page_no, mtr_t *mtr)
UNIV_INTERN ibool trx_purge_update_undo_must_exist(trx_id_t trx_id)
#define mem_heap_create(N)
UNIV_INTERN trx_undo_rec_t * trx_purge_fetch_next_rec(roll_ptr_t *roll_ptr, trx_undo_inf_t **cell, mem_heap_t *heap)
UNIV_INTERN trx_undo_rec_t * trx_undo_get_next_rec(trx_undo_rec_t *rec, ulint page_no, ulint offset, mtr_t *mtr)
#define UT_LIST_GET_FIRST(BASE)
UNIV_INLINE trx_undo_rec_t * trx_undo_page_get_next_rec(trx_undo_rec_t *rec, ulint page_no, ulint offset)
UNIV_INLINE void mem_heap_empty(mem_heap_t *heap)
UNIV_INLINE undo_no_t trx_undo_rec_get_undo_no(const trx_undo_rec_t *undo_rec)
UNIV_INTERN void flst_cut_end(flst_base_node_t *base, flst_node_t *node2, ulint n_nodes, mtr_t *mtr)
UNIV_INTERN void ib_bh_pop(ib_bh_t *ib_bh)
UNIV_INTERN trx_undo_arr_t * trx_undo_arr_create(void)
UNIV_INTERN trx_undo_rec_t * trx_undo_get_first_rec(ulint space, ulint zip_size, ulint page_no, ulint offset, ulint mode, mtr_t *mtr)
UNIV_INTERN void flst_add_first(flst_base_node_t *base, flst_node_t *node, mtr_t *mtr)
UNIV_INTERN sess_t * sess_open(void)
UNIV_INTERN void trx_purge_add_update_undo_to_history(trx_t *trx, page_t *undo_page, mtr_t *mtr)
UNIV_INLINE trx_undo_rec_t * trx_undo_rec_copy(const trx_undo_rec_t *undo_rec, mem_heap_t *heap)
UNIV_INTERN purge_node_t * row_purge_node_create(que_thr_t *parent, mem_heap_t *heap)
UNIV_INTERN void ut_print_timestamp(FILE *file)
UNIV_INTERN void read_view_print(const read_view_t *view)
UNIV_INLINE void * ib_bh_first(ib_bh_t *ib_bh)
UNIV_INTERN void trx_purge_sys_close(void)
UNIV_INLINE void mtr_start(mtr_t *mtr) __attribute__((nonnull))
#define TRX_UNDO_DEL_MARKS
UNIV_INLINE ulint mach_read_from_2(const byte *b) __attribute__((nonnull
UNIV_INTERN void srv_wake_purge_thread_if_not_active(void)
UNIV_INTERN que_thr_t * que_thr_create(que_fork_t *parent, mem_heap_t *heap)
UNIV_INLINE ibool trx_undo_rec_get_extern_storage(const trx_undo_rec_t *undo_rec)
#define TRX_UNDO_PAGE_LIST
UNIV_INLINE ib_uint64_t mach_read_from_8(const byte *b) __attribute__((nonnull
UNIV_INTERN que_thr_t * que_fork_start_command(que_fork_t *fork)
UNIV_INLINE ulint flst_get_len(const flst_base_node_t *base, mtr_t *mtr)
#define UT_LIST_GET_LAST(BASE)
UNIV_INTERN void ib_bh_free(ib_bh_t *ib_bh)
UNIV_INTERN ibool trx_start_low(trx_t *trx, ulint rseg_id)
#define TRX_UNDO_HISTORY_NODE
UNIV_INLINE page_t * trx_undo_page_get_s_latched(ulint space, ulint zip_size, ulint page_no, mtr_t *mtr)
UNIV_INTERN void trx_undo_arr_free(trx_undo_arr_t *arr)
UNIV_INTERN ibool fseg_free_step_not_header(fseg_header_t *header, mtr_t *mtr)
UNIV_INTERN ibool fseg_free_step(fseg_header_t *header, mtr_t *mtr)
UNIV_INLINE void trx_rsegf_set_nth_undo(trx_rsegf_t *rsegf, ulint n, ulint page_no, mtr_t *mtr)
UNIV_INTERN que_fork_t * que_fork_create(que_t *graph, que_node_t *parent, ulint fork_type, mem_heap_t *heap)