Loading innobase/include/rem0rec.ic +56 −25 Original line number Diff line number Diff line Loading @@ -40,8 +40,18 @@ most significant bytes and bits are written below less significant. (1) byte offset (2) bit usage within byte downward from origin -> 1 8 bits pointer to next record (relative) 2 8 bits pointer to next record (relative) origin -> 1 8 bits relative offset of next record 2 8 bits relative offset of next record the relative offset is an unsigned 16-bit integer: (offset_of_next_record - offset_of_this_record) mod 64Ki, where mod is the modulo as a non-negative number; we can calculate the the offset of the next record with the formula: relative_offset + offset_of_this_record mod UNIV_PAGE_SIZE 3 3 bits status: 000=conventional record 001=node pointer record (inside B-tree) Loading Loading @@ -252,26 +262,37 @@ UNIV_INLINE ulint rec_get_next_offs( /*==============*/ /* out: the page offset of the next chained record */ /* out: the page offset of the next chained record, or 0 if none */ rec_t* rec, /* in: physical record */ ibool comp) /* in: TRUE=compact page format */ { ulint field_value; ut_ad(REC_NEXT_MASK == 0xFFFFUL); ut_ad(REC_NEXT_SHIFT == 0); field_value = mach_read_from_2(rec - REC_NEXT); if (comp) { lint ret = (signed short) rec_get_bit_field_2(rec, REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT); #if UNIV_PAGE_SIZE <= 32768 /* with 64 KiB page size, the pointer will "wrap around", and the following assertions are invalid */ ut_ad(ret + ut_align_offset(rec, UNIV_PAGE_SIZE) < UNIV_PAGE_SIZE); /* Note that for 64 KiB pages, field_value can 'wrap around' and the debug assertion is not valid */ ut_ad((int16_t)field_value + ut_align_offset(rec, UNIV_PAGE_SIZE) < UNIV_PAGE_SIZE); #endif return(ret ? ut_align_offset(rec + ret, UNIV_PAGE_SIZE) : 0); if (field_value == 0) { return(0); } else { ulint ret = rec_get_bit_field_2(rec, REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT); ut_ad(ret < UNIV_PAGE_SIZE); return(ret); return(ut_align_offset(rec + field_value, UNIV_PAGE_SIZE)); } else { ut_ad(field_value < UNIV_PAGE_SIZE); return(field_value); } } Loading @@ -284,21 +305,31 @@ rec_set_next_offs( /*==============*/ rec_t* rec, /* in: physical record */ ibool comp, /* in: TRUE=compact page format */ ulint next) /* in: offset of the next record */ ulint next) /* in: offset of the next record, or 0 if none */ { ut_ad(rec); ut_ad(UNIV_PAGE_SIZE > next); ut_ad(REC_NEXT_MASK == 0xFFFFUL); ut_ad(REC_NEXT_SHIFT == 0); if (comp) { rec_set_bit_field_2(rec, next ? (next - ut_align_offset(rec, UNIV_PAGE_SIZE)) #ifdef UNIV_DEBUG /* avoid an assertion failure */ & (REC_NEXT_MASK >> REC_NEXT_SHIFT) #endif : 0, REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT); ulint field_value; if (next) { /* The following two statements calculate next - offset_of_rec mod 64Ki, where mod is the modulo as a non-negative number */ field_value = (ulint)((lint)next - (lint)ut_align_offset(rec, UNIV_PAGE_SIZE)); field_value &= REC_NEXT_MASK; } else { field_value = 0; } mach_write_to_2(rec - REC_NEXT, field_value); } else { rec_set_bit_field_2(rec, next, REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT); mach_write_to_2(rec - REC_NEXT, next); } } Loading innobase/include/trx0roll.h +12 −4 Original line number Diff line number Diff line Loading @@ -105,11 +105,19 @@ trx_rollback( Rollback or clean up transactions which have no user session. If the transaction already was committed, then we clean up a possible insert undo log. If the transaction was not yet committed, then we roll it back. Note: this is done in a background thread */ Note: this is done in a background thread. */ #ifndef __WIN__ void* trx_rollback_or_clean_all_without_sess(void *); /*============================================*/ #else ulint #endif trx_rollback_or_clean_all_without_sess( /*===================================*/ /* out: a dummy parameter */ void* arg __attribute__((unused))); /* in: a dummy parameter required by os_thread_create */ /******************************************************************** Finishes a transaction rollback. */ Loading innobase/log/log0recv.c +0 −1 Original line number Diff line number Diff line Loading @@ -2937,7 +2937,6 @@ recv_recovery_from_checkpoint_finish(void) #ifndef UNIV_LOG_DEBUG recv_sys_free(); #endif if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) { os_thread_create(trx_rollback_or_clean_all_without_sess, (void *)&i, &recovery_thread_id); Loading innobase/srv/srv0start.c +5 −7 Original line number Diff line number Diff line Loading @@ -1403,15 +1403,13 @@ NetWare. */ fsp_header_inc_size(0, sum_of_new_sizes, &mtr); mtr_commit(&mtr); } if (recv_needed_recovery) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Flushing modified pages from the buffer pool...\n"); } /* Immediately write the log record about increased tablespace size to disk, so that it is durable even if mysqld would crash quickly */ log_make_checkpoint_at(ut_dulint_max, TRUE); log_buffer_flush_to_disk(); } #ifdef UNIV_LOG_ARCHIVE /* Archiving is always off under MySQL */ Loading innobase/trx/trx0roll.c +51 −18 Original line number Diff line number Diff line Loading @@ -30,9 +30,13 @@ Created 3/26/1996 Heikki Tuuri /* This many pages must be undone before a truncate is tried within rollback */ #define TRX_ROLL_TRUNC_THRESHOLD 1 /* In crash recovery, the current trx to be rolled back */ trx_t* trx_roll_crash_recv_trx = NULL; /* In crash recovery we set this to the undo n:o of the current trx to be rolled back. Then we can print how many % the rollback has progressed. */ ib_longlong trx_roll_max_undo_no; /* Auxiliary variable which tells the previous progress % we printed */ ulint trx_roll_progress_printed_pct; Loading Loading @@ -332,11 +336,19 @@ trx_savept_take( Rollback or clean up transactions which have no user session. If the transaction already was committed, then we clean up a possible insert undo log. If the transaction was not yet committed, then we roll it back. Note: this is done in a background thread */ Note: this is done in a background thread. */ #ifndef __WIN__ void* trx_rollback_or_clean_all_without_sess(void *i) /*========================================*/ #else ulint #endif trx_rollback_or_clean_all_without_sess( /*===================================*/ /* out: a dummy parameter */ void* arg __attribute__((unused))) /* in: a dummy parameter required by os_thread_create */ { mem_heap_t* heap; que_fork_t* fork; Loading @@ -361,9 +373,9 @@ trx_rollback_or_clean_all_without_sess(void *i) if (UT_LIST_GET_FIRST(trx_sys->trx_list)) { fprintf(stderr, "InnoDB: Starting rollback of uncommitted transactions\n"); "InnoDB: Starting in background the rollback of uncommitted transactions\n"); } else { os_thread_exit(i); goto leave_function; } loop: heap = mem_heap_create(512); Loading @@ -373,7 +385,6 @@ trx_rollback_or_clean_all_without_sess(void *i) trx = UT_LIST_GET_FIRST(trx_sys->trx_list); while (trx) { if ((trx->sess || (trx->conc_state == TRX_NOT_STARTED))) { trx = UT_LIST_GET_NEXT(trx_list, trx); } else if (trx->conc_state == TRX_PREPARED) { Loading @@ -386,17 +397,17 @@ trx_rollback_or_clean_all_without_sess(void *i) mutex_exit(&kernel_mutex); if (trx == NULL) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Rollback of uncommitted transactions completed\n"); mem_heap_free(heap); os_thread_exit(i); goto leave_function; } trx->sess = trx_dummy_sess; if (trx->conc_state == TRX_COMMITTED_IN_MEMORY) { fprintf(stderr, "InnoDB: Cleaning up trx with id %lu %lu\n", (ulong) ut_dulint_get_high(trx->id), Loading Loading @@ -425,21 +436,28 @@ trx_rollback_or_clean_all_without_sess(void *i) ut_a(thr == que_fork_start_command(fork)); trx_roll_crash_recv_trx = trx; trx_roll_max_undo_no = ut_conv_dulint_to_longlong(trx->undo_no); trx_roll_progress_printed_pct = 0; rows_to_undo = trx_roll_max_undo_no; if (rows_to_undo > 1000000000) { rows_to_undo = rows_to_undo / 1000000; unit = "M"; } ut_print_timestamp(stderr); fprintf(stderr, "InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo", " InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo\n", (ulong) ut_dulint_get_high(trx->id), (ulong) ut_dulint_get_low(trx->id), (ulong) rows_to_undo, unit); mutex_exit(&kernel_mutex); trx->mysql_thread_id = os_thread_get_curr_id(); trx->mysql_process_no = os_proc_get_number(); if (trx->dict_operation) { row_mysql_lock_data_dictionary(trx); } Loading Loading @@ -493,9 +511,23 @@ trx_rollback_or_clean_all_without_sess(void *i) (ulong) ut_dulint_get_low(trx->id)); mem_heap_free(heap); trx_roll_crash_recv_trx = NULL; goto loop; os_thread_exit(i); /* not reached */ leave_function: /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ os_thread_exit(NULL); /* The following is dummy code to keep the compiler happy: */ #ifndef __WIN__ return(NULL); #else return(0); #endif } /*********************************************************************** Loading Loading @@ -856,16 +888,17 @@ trx_roll_pop_top_rec_of_trx( ut_ad(ut_dulint_cmp(ut_dulint_add(undo_no, 1), trx->undo_no) == 0); /* We print rollback progress info if we are in a crash recovery and the transaction has at least 1000 row operations to undo */ and the transaction has at least 1000 row operations to undo. */ if (trx == trx_roll_crash_recv_trx && trx_roll_max_undo_no > 1000) { if (srv_is_being_started && trx_roll_max_undo_no > 1000) { progress_pct = 100 - (ulint) ((ut_conv_dulint_to_longlong(undo_no) * 100) / trx_roll_max_undo_no); if (progress_pct != trx_roll_progress_printed_pct) { if (trx_roll_progress_printed_pct == 0) { fprintf(stderr, "\nInnoDB: Progress in percents: %lu", (ulong) progress_pct); "\nInnoDB: Progress in percents: %lu\n", (ulong) progress_pct); } else { fprintf(stderr, " %lu", (ulong) progress_pct); Loading Loading
innobase/include/rem0rec.ic +56 −25 Original line number Diff line number Diff line Loading @@ -40,8 +40,18 @@ most significant bytes and bits are written below less significant. (1) byte offset (2) bit usage within byte downward from origin -> 1 8 bits pointer to next record (relative) 2 8 bits pointer to next record (relative) origin -> 1 8 bits relative offset of next record 2 8 bits relative offset of next record the relative offset is an unsigned 16-bit integer: (offset_of_next_record - offset_of_this_record) mod 64Ki, where mod is the modulo as a non-negative number; we can calculate the the offset of the next record with the formula: relative_offset + offset_of_this_record mod UNIV_PAGE_SIZE 3 3 bits status: 000=conventional record 001=node pointer record (inside B-tree) Loading Loading @@ -252,26 +262,37 @@ UNIV_INLINE ulint rec_get_next_offs( /*==============*/ /* out: the page offset of the next chained record */ /* out: the page offset of the next chained record, or 0 if none */ rec_t* rec, /* in: physical record */ ibool comp) /* in: TRUE=compact page format */ { ulint field_value; ut_ad(REC_NEXT_MASK == 0xFFFFUL); ut_ad(REC_NEXT_SHIFT == 0); field_value = mach_read_from_2(rec - REC_NEXT); if (comp) { lint ret = (signed short) rec_get_bit_field_2(rec, REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT); #if UNIV_PAGE_SIZE <= 32768 /* with 64 KiB page size, the pointer will "wrap around", and the following assertions are invalid */ ut_ad(ret + ut_align_offset(rec, UNIV_PAGE_SIZE) < UNIV_PAGE_SIZE); /* Note that for 64 KiB pages, field_value can 'wrap around' and the debug assertion is not valid */ ut_ad((int16_t)field_value + ut_align_offset(rec, UNIV_PAGE_SIZE) < UNIV_PAGE_SIZE); #endif return(ret ? ut_align_offset(rec + ret, UNIV_PAGE_SIZE) : 0); if (field_value == 0) { return(0); } else { ulint ret = rec_get_bit_field_2(rec, REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT); ut_ad(ret < UNIV_PAGE_SIZE); return(ret); return(ut_align_offset(rec + field_value, UNIV_PAGE_SIZE)); } else { ut_ad(field_value < UNIV_PAGE_SIZE); return(field_value); } } Loading @@ -284,21 +305,31 @@ rec_set_next_offs( /*==============*/ rec_t* rec, /* in: physical record */ ibool comp, /* in: TRUE=compact page format */ ulint next) /* in: offset of the next record */ ulint next) /* in: offset of the next record, or 0 if none */ { ut_ad(rec); ut_ad(UNIV_PAGE_SIZE > next); ut_ad(REC_NEXT_MASK == 0xFFFFUL); ut_ad(REC_NEXT_SHIFT == 0); if (comp) { rec_set_bit_field_2(rec, next ? (next - ut_align_offset(rec, UNIV_PAGE_SIZE)) #ifdef UNIV_DEBUG /* avoid an assertion failure */ & (REC_NEXT_MASK >> REC_NEXT_SHIFT) #endif : 0, REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT); ulint field_value; if (next) { /* The following two statements calculate next - offset_of_rec mod 64Ki, where mod is the modulo as a non-negative number */ field_value = (ulint)((lint)next - (lint)ut_align_offset(rec, UNIV_PAGE_SIZE)); field_value &= REC_NEXT_MASK; } else { field_value = 0; } mach_write_to_2(rec - REC_NEXT, field_value); } else { rec_set_bit_field_2(rec, next, REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT); mach_write_to_2(rec - REC_NEXT, next); } } Loading
innobase/include/trx0roll.h +12 −4 Original line number Diff line number Diff line Loading @@ -105,11 +105,19 @@ trx_rollback( Rollback or clean up transactions which have no user session. If the transaction already was committed, then we clean up a possible insert undo log. If the transaction was not yet committed, then we roll it back. Note: this is done in a background thread */ Note: this is done in a background thread. */ #ifndef __WIN__ void* trx_rollback_or_clean_all_without_sess(void *); /*============================================*/ #else ulint #endif trx_rollback_or_clean_all_without_sess( /*===================================*/ /* out: a dummy parameter */ void* arg __attribute__((unused))); /* in: a dummy parameter required by os_thread_create */ /******************************************************************** Finishes a transaction rollback. */ Loading
innobase/log/log0recv.c +0 −1 Original line number Diff line number Diff line Loading @@ -2937,7 +2937,6 @@ recv_recovery_from_checkpoint_finish(void) #ifndef UNIV_LOG_DEBUG recv_sys_free(); #endif if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) { os_thread_create(trx_rollback_or_clean_all_without_sess, (void *)&i, &recovery_thread_id); Loading
innobase/srv/srv0start.c +5 −7 Original line number Diff line number Diff line Loading @@ -1403,15 +1403,13 @@ NetWare. */ fsp_header_inc_size(0, sum_of_new_sizes, &mtr); mtr_commit(&mtr); } if (recv_needed_recovery) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Flushing modified pages from the buffer pool...\n"); } /* Immediately write the log record about increased tablespace size to disk, so that it is durable even if mysqld would crash quickly */ log_make_checkpoint_at(ut_dulint_max, TRUE); log_buffer_flush_to_disk(); } #ifdef UNIV_LOG_ARCHIVE /* Archiving is always off under MySQL */ Loading
innobase/trx/trx0roll.c +51 −18 Original line number Diff line number Diff line Loading @@ -30,9 +30,13 @@ Created 3/26/1996 Heikki Tuuri /* This many pages must be undone before a truncate is tried within rollback */ #define TRX_ROLL_TRUNC_THRESHOLD 1 /* In crash recovery, the current trx to be rolled back */ trx_t* trx_roll_crash_recv_trx = NULL; /* In crash recovery we set this to the undo n:o of the current trx to be rolled back. Then we can print how many % the rollback has progressed. */ ib_longlong trx_roll_max_undo_no; /* Auxiliary variable which tells the previous progress % we printed */ ulint trx_roll_progress_printed_pct; Loading Loading @@ -332,11 +336,19 @@ trx_savept_take( Rollback or clean up transactions which have no user session. If the transaction already was committed, then we clean up a possible insert undo log. If the transaction was not yet committed, then we roll it back. Note: this is done in a background thread */ Note: this is done in a background thread. */ #ifndef __WIN__ void* trx_rollback_or_clean_all_without_sess(void *i) /*========================================*/ #else ulint #endif trx_rollback_or_clean_all_without_sess( /*===================================*/ /* out: a dummy parameter */ void* arg __attribute__((unused))) /* in: a dummy parameter required by os_thread_create */ { mem_heap_t* heap; que_fork_t* fork; Loading @@ -361,9 +373,9 @@ trx_rollback_or_clean_all_without_sess(void *i) if (UT_LIST_GET_FIRST(trx_sys->trx_list)) { fprintf(stderr, "InnoDB: Starting rollback of uncommitted transactions\n"); "InnoDB: Starting in background the rollback of uncommitted transactions\n"); } else { os_thread_exit(i); goto leave_function; } loop: heap = mem_heap_create(512); Loading @@ -373,7 +385,6 @@ trx_rollback_or_clean_all_without_sess(void *i) trx = UT_LIST_GET_FIRST(trx_sys->trx_list); while (trx) { if ((trx->sess || (trx->conc_state == TRX_NOT_STARTED))) { trx = UT_LIST_GET_NEXT(trx_list, trx); } else if (trx->conc_state == TRX_PREPARED) { Loading @@ -386,17 +397,17 @@ trx_rollback_or_clean_all_without_sess(void *i) mutex_exit(&kernel_mutex); if (trx == NULL) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Rollback of uncommitted transactions completed\n"); mem_heap_free(heap); os_thread_exit(i); goto leave_function; } trx->sess = trx_dummy_sess; if (trx->conc_state == TRX_COMMITTED_IN_MEMORY) { fprintf(stderr, "InnoDB: Cleaning up trx with id %lu %lu\n", (ulong) ut_dulint_get_high(trx->id), Loading Loading @@ -425,21 +436,28 @@ trx_rollback_or_clean_all_without_sess(void *i) ut_a(thr == que_fork_start_command(fork)); trx_roll_crash_recv_trx = trx; trx_roll_max_undo_no = ut_conv_dulint_to_longlong(trx->undo_no); trx_roll_progress_printed_pct = 0; rows_to_undo = trx_roll_max_undo_no; if (rows_to_undo > 1000000000) { rows_to_undo = rows_to_undo / 1000000; unit = "M"; } ut_print_timestamp(stderr); fprintf(stderr, "InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo", " InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo\n", (ulong) ut_dulint_get_high(trx->id), (ulong) ut_dulint_get_low(trx->id), (ulong) rows_to_undo, unit); mutex_exit(&kernel_mutex); trx->mysql_thread_id = os_thread_get_curr_id(); trx->mysql_process_no = os_proc_get_number(); if (trx->dict_operation) { row_mysql_lock_data_dictionary(trx); } Loading Loading @@ -493,9 +511,23 @@ trx_rollback_or_clean_all_without_sess(void *i) (ulong) ut_dulint_get_low(trx->id)); mem_heap_free(heap); trx_roll_crash_recv_trx = NULL; goto loop; os_thread_exit(i); /* not reached */ leave_function: /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ os_thread_exit(NULL); /* The following is dummy code to keep the compiler happy: */ #ifndef __WIN__ return(NULL); #else return(0); #endif } /*********************************************************************** Loading Loading @@ -856,16 +888,17 @@ trx_roll_pop_top_rec_of_trx( ut_ad(ut_dulint_cmp(ut_dulint_add(undo_no, 1), trx->undo_no) == 0); /* We print rollback progress info if we are in a crash recovery and the transaction has at least 1000 row operations to undo */ and the transaction has at least 1000 row operations to undo. */ if (trx == trx_roll_crash_recv_trx && trx_roll_max_undo_no > 1000) { if (srv_is_being_started && trx_roll_max_undo_no > 1000) { progress_pct = 100 - (ulint) ((ut_conv_dulint_to_longlong(undo_no) * 100) / trx_roll_max_undo_no); if (progress_pct != trx_roll_progress_printed_pct) { if (trx_roll_progress_printed_pct == 0) { fprintf(stderr, "\nInnoDB: Progress in percents: %lu", (ulong) progress_pct); "\nInnoDB: Progress in percents: %lu\n", (ulong) progress_pct); } else { fprintf(stderr, " %lu", (ulong) progress_pct); Loading