29 #include "trx0roll.ic"
48 #define TRX_ROLL_TRUNC_THRESHOLD 1
51 static const trx_t* trx_roll_crash_recv_trx = NULL;
58 static ulint trx_roll_progress_printed_pct;
89 roll_node->
savept = *savept;
99 mutex_enter(&kernel_mutex);
101 while (trx->
que_state != TRX_QUE_RUNNING) {
103 mutex_exit(&kernel_mutex);
107 mutex_enter(&kernel_mutex);
110 mutex_exit(&kernel_mutex);
169 trx->
op_info =
"rollback of SQL statement";
217 while (savep != NULL) {
240 const char* savepoint_name,
241 ib_int64_t* mysql_binlog_cache_pos)
253 while (savep != NULL) {
263 return(DB_NO_SAVEPOINT);
268 fputs(
" InnoDB: Error: transaction has a savepoint ", stderr);
270 fputs(
" though it is not started\n", stderr);
280 trx->
op_info =
"rollback to a savepoint";
305 const char* savepoint_name,
306 ib_int64_t binlog_cache_pos)
314 ut_a(savepoint_name);
320 while (savep != NULL) {
362 const char* savepoint_name)
369 while (savep != NULL) {
377 return(DB_NO_SAVEPOINT);
391 return(trx == trx_roll_crash_recv_trx);
423 ib_int64_t rows_to_undo;
424 const char* unit =
"";
425 ibool dictionary_locked = FALSE;
436 thr->
child = roll_node;
439 mutex_enter(&kernel_mutex);
445 trx_roll_crash_recv_trx = trx;
446 trx_roll_max_undo_no = trx->
undo_no;
447 trx_roll_progress_printed_pct = 0;
448 rows_to_undo = trx_roll_max_undo_no;
450 if (rows_to_undo > 1000000000) {
451 rows_to_undo = rows_to_undo / 1000000;
457 " InnoDB: Rolling back trx with id " TRX_ID_FMT ", %lu%s"
460 (ulong) rows_to_undo, unit);
461 mutex_exit(&kernel_mutex);
468 row_mysql_lock_data_dictionary(trx);
469 dictionary_locked = TRUE;
474 mutex_enter(&kernel_mutex);
476 while (trx->
que_state != TRX_QUE_RUNNING) {
478 mutex_exit(&kernel_mutex);
481 "InnoDB: Waiting for rollback of trx id "
486 mutex_enter(&kernel_mutex);
489 mutex_exit(&kernel_mutex);
498 "InnoDB: Dropping table with id %llu"
499 " in recovery if it exists\n",
507 fputs(
"InnoDB: Table found: dropping table ", stderr);
509 fputs(
" in recovery\n", stderr);
514 ut_a(err == (
int) DB_SUCCESS);
518 if (dictionary_locked) {
522 fprintf(stderr,
"\nInnoDB: Rolling back of trx id " TRX_ID_FMT
527 trx_roll_crash_recv_trx = NULL;
544 mutex_enter(&kernel_mutex);
552 "InnoDB: Starting in background the rollback"
553 " of uncommitted transactions\n");
556 mutex_exit(&kernel_mutex);
559 mutex_enter(&kernel_mutex);
568 case TRX_NOT_STARTED:
572 case TRX_COMMITTED_IN_MEMORY:
573 mutex_exit(&kernel_mutex);
575 "InnoDB: Cleaning up trx with id "
584 mutex_exit(&kernel_mutex);
585 trx_rollback_active(trx);
594 " InnoDB: Rollback of non-prepared"
595 " transactions completed\n");
599 mutex_exit(&kernel_mutex);
617 #ifdef UNIV_PFS_THREAD
618 pfs_register_thread(trx_rollback_clean_thread_key);
628 OS_THREAD_DUMMY_RETURN;
648 * UNIV_MAX_PARALLELISM));
649 arr->
n_cells = UNIV_MAX_PARALLELISM;
654 for (i = 0; i < UNIV_MAX_PARALLELISM; i++) {
680 trx_undo_arr_store_info(
713 if (cell->
undo_no == undo_no) {
716 stored_here->
in_use = FALSE;
727 if (n == n_used && stored_here) {
740 trx_undo_arr_remove_info(
770 trx_undo_arr_get_biggest(
823 biggest = trx_undo_arr_get_biggest(arr);
825 if (biggest >= limit) {
846 trx_roll_pop_top_rec(
870 if (prev_rec == NULL) {
876 if (prev_rec_page != undo_page) {
886 return(undo_page + offset);
922 mutex_enter(&(rseg->
mutex));
926 mutex_exit(&(rseg->
mutex));
932 if (!ins_undo || ins_undo->
empty) {
934 }
else if (!upd_undo || upd_undo->
empty) {
942 if (!undo || undo->
empty
948 mutex_enter(&(rseg->
mutex));
952 mutex_exit(&(rseg->
mutex));
960 if (undo == ins_undo) {
971 undo_rec = trx_roll_pop_top_rec(trx, undo, &mtr);
980 if (trx == trx_roll_crash_recv_trx && trx_roll_max_undo_no > 1000) {
982 progress_pct = 100 - (ulint)
983 ((undo_no * 100) / trx_roll_max_undo_no);
984 if (progress_pct != trx_roll_progress_printed_pct) {
985 if (trx_roll_progress_printed_pct == 0) {
987 "\nInnoDB: Progress in percents:"
988 " %lu", (ulong) progress_pct);
991 " %lu", (ulong) progress_pct);
994 trx_roll_progress_printed_pct = progress_pct;
1000 if (!trx_undo_arr_store_info(trx, undo_no)) {
1016 return(undo_rec_copy);
1035 ret = trx_undo_arr_store_info(trx, undo_no);
1057 trx_undo_arr_remove_info(arr, undo_no);
1081 ut_ad(mutex_own(&kernel_mutex));
1086 switch (sig->
type) {
1087 case TRX_SIG_TOTAL_ROLLBACK:
1090 case TRX_SIG_ROLLBACK_TO_SAVEPT:
1093 case TRX_SIG_ERROR_OCCURRED:
1112 trx->
graph = roll_graph;
1123 if (next_thr && (*next_thr == NULL)) {
1149 ut_ad(mutex_own(&kernel_mutex));
1169 trx_finish_error_processing(
1176 ut_ad(mutex_own(&kernel_mutex));
1180 while (sig != NULL) {
1183 if (sig->
type == TRX_SIG_ERROR_OCCURRED) {
1198 trx_finish_partial_rollback_off_kernel(
1209 ut_ad(mutex_own(&kernel_mutex));
1240 ut_ad(mutex_own(&kernel_mutex));
1249 if (sig->
type == TRX_SIG_ROLLBACK_TO_SAVEPT) {
1251 trx_finish_partial_rollback_off_kernel(trx, next_thr);
1255 }
else if (sig->
type == TRX_SIG_ERROR_OCCURRED) {
1257 trx_finish_error_processing(trx);
1263 if (lock_print_waits) {
1264 fprintf(stderr,
"Trx " TRX_ID_FMT " rollback finished\n",
1276 while (sig != NULL) {
1279 if (sig->
type == TRX_SIG_TOTAL_ROLLBACK) {
1333 mutex_enter(&kernel_mutex);
1338 sig_no = TRX_SIG_ROLLBACK_TO_SAVEPT;
1339 savept = &(node->
savept);
1341 sig_no = TRX_SIG_TOTAL_ROLLBACK;
1350 thr->
state = QUE_THR_SIG_REPLY_WAIT;
1352 mutex_exit(&kernel_mutex);
UNIV_INTERN ulint trx_savepoint_for_mysql(trx_t *trx, const char *savepoint_name, ib_int64_t binlog_cache_pos)
#define UT_LIST_GET_LEN(BASE)
UNIV_INTERN ulint trx_release_savepoint_for_mysql(trx_t *trx, const char *savepoint_name)
UNIV_INTERN void trx_roll_savepoint_free(trx_t *trx, trx_named_savept_t *savep)
#define UT_LIST_GET_NEXT(NAME, N)
UNIV_INTERN void trx_cleanup_at_db_startup(trx_t *trx)
UNIV_INLINE void trx_start_if_not_started(trx_t *trx)
UNIV_INTERN int trx_rollback_for_mysql(trx_t *trx)
UNIV_INTERN ibool trx_is_recv(const trx_t *trx)
UNIV_INLINE page_t * page_align(const void *ptr) __attribute__((const ))
UNIV_INTERN que_thr_t * pars_complete_graph_for_exec(que_node_t *node, trx_t *trx, mem_heap_t *heap)
UNIV_INLINE ulint page_get_page_no(const page_t *page)
trx_undo_arr_t * undo_no_arr
UNIV_INLINE dict_table_t * dict_table_get_on_id_low(table_id_t table_id)
UNIV_INTERN void trx_roll_savepoints_free(trx_t *trx, trx_named_savept_t *savep)
UNIV_INTERN void srv_active_wake_master_thread(void)
enum roll_node_state state
UNIV_INTERN void que_run_threads(que_thr_t *thr)
UNIV_INTERN int trx_general_rollback_for_mysql(trx_t *trx, trx_savept_t *savept)
#define mem_heap_free(heap)
UNIV_INTERN ulint trx_commit_for_mysql(trx_t *trx)
UNIV_INTERN trx_savept_t trx_savept_take(trx_t *trx)
UNIV_INTERN roll_node_t * roll_node_create(mem_heap_t *heap)
UNIV_INTERN trx_undo_rec_t * trx_roll_pop_top_rec_of_trx(trx_t *trx, undo_no_t limit, roll_ptr_t *roll_ptr, mem_heap_t *heap)
UNIV_INTERN void trx_sig_reply(trx_sig_t *sig, que_thr_t **next_thr)
UNIV_INTERN void mtr_commit(mtr_t *mtr) __attribute__((nonnull))
#define UT_LIST_REMOVE(NAME, BASE, N)
UNIV_INTERN void srv_que_task_enqueue_low(que_thr_t *thr)
UNIV_INLINE roll_ptr_t trx_undo_build_roll_ptr(ibool is_insert, ulint rseg_id, ulint page_no, ulint offset)
UNIV_INLINE trx_undo_inf_t * trx_undo_arr_get_nth_info(trx_undo_arr_t *arr, ulint n)
UNIV_INTERN void que_graph_free(que_t *graph)
UNIV_INTERN ulint os_proc_get_number(void)
UNIV_INTERN ulint trx_rollback_to_savepoint_for_mysql(trx_t *trx, const char *savepoint_name, ib_int64_t *mysql_binlog_cache_pos)
UNIV_INTERN void os_thread_sleep(ulint tm)
UNIV_INTERN void trx_sig_remove(trx_t *trx, trx_sig_t *sig)
UNIV_INTERN void ut_print_name(FILE *f, struct trx_struct *trx, ibool table_id, const char *name)
UNIV_INLINE void * mem_heap_alloc(mem_heap_t *heap, ulint n)
#define mem_heap_create(N)
UNIV_INTERN ibool trx_undo_rec_reserve(trx_t *trx, undo_no_t undo_no)
UNIV_INTERN void trx_sig_send(trx_t *trx, ulint type, ulint sender, que_thr_t *receiver_thr, trx_savept_t *savept, que_thr_t **next_thr)
UNIV_INTERN void trx_roll_try_truncate(trx_t *trx)
#define UT_LIST_ADD_LAST(NAME, BASE, N)
#define UT_LIST_GET_FIRST(BASE)
UNIV_INLINE undo_no_t trx_undo_rec_get_undo_no(const trx_undo_rec_t *undo_rec)
UNIV_INTERN int trx_rollback_last_sql_stat_for_mysql(trx_t *trx)
UNIV_INTERN void trx_mark_sql_stat_end(trx_t *trx)
UNIV_INTERN trx_undo_arr_t * trx_undo_arr_create(void)
UNIV_INTERN void trx_commit_off_kernel(trx_t *trx)
UNIV_INLINE que_node_t * que_node_get_parent(que_node_t *node)
UNIV_INLINE char * mem_strdup(const char *str)
UNIV_INLINE trx_undo_rec_t * trx_undo_rec_copy(const trx_undo_rec_t *undo_rec, mem_heap_t *heap)
UNIV_INLINE enum trx_dict_op trx_get_dict_operation(const trx_t *trx) __attribute__((pure))
UNIV_INLINE ulint que_node_get_type(que_node_t *node)
UNIV_INTERN void trx_undo_rec_release(trx_t *trx, undo_no_t undo_no)
UNIV_INTERN void trx_rollback(trx_t *trx, trx_sig_t *sig, que_thr_t **next_thr)
UNIV_INTERN que_t * trx_roll_graph_build(trx_t *trx)
UNIV_INTERN void ut_print_timestamp(FILE *file)
UNIV_INTERN os_thread_ret_t trx_rollback_or_clean_all_recovered(void *arg)
UNIV_INLINE trx_t * thr_get_trx(que_thr_t *thr)
UNIV_INTERN os_thread_id_t os_thread_get_curr_id(void)
UNIV_INTERN void trx_rollback_or_clean_recovered(ibool all)
UNIV_INTERN que_thr_t * trx_rollback_step(que_thr_t *thr)
UNIV_INTERN void os_thread_exit(void *exit_value)
UNIV_INTERN void trx_finish_rollback_off_kernel(que_t *graph, trx_t *trx, que_thr_t **next_thr)
UNIV_INLINE void mtr_start(mtr_t *mtr) __attribute__((nonnull))
ib_int64_t mysql_binlog_cache_pos
UNIV_INTERN void trx_undo_truncate_end(trx_t *trx, trx_undo_t *undo, undo_no_t limit)
UNIV_INTERN undo_node_t * row_undo_node_create(trx_t *trx, que_thr_t *parent, mem_heap_t *heap)
UNIV_INTERN que_thr_t * que_thr_create(que_fork_t *parent, mem_heap_t *heap)
UNIV_INTERN que_thr_t * que_fork_start_command(que_fork_t *fork)
UNIV_INTERN void row_mysql_unlock_data_dictionary(trx_t *trx)
UNIV_INTERN int row_drop_table_for_mysql(const char *name, trx_t *trx, ibool drop_db)
UNIV_INLINE int ut_strcmp(const char *str1, const char *str2)
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 que_fork_t * que_fork_create(que_t *graph, que_node_t *parent, ulint fork_type, mem_heap_t *heap)
UNIV_INTERN trx_undo_rec_t * trx_undo_get_prev_rec(trx_undo_rec_t *rec, ulint page_no, ulint offset, mtr_t *mtr)