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);