29 #include "trx0roll.ic"
51 #define TRX_ROLL_TRUNC_THRESHOLD 1
54 static const trx_t* trx_roll_crash_recv_trx = NULL;
61 static ulint trx_roll_progress_printed_pct;
75 trx_rollback_to_savepoint_low(
92 roll_node->
savept = *savept;
116 if (savept == NULL) {
117 trx_rollback_finish(trx);
129 MONITOR_DEC(MONITOR_TRX_ACTIVE);
151 trx_start_if_not_started_xa(trx);
153 trx_rollback_to_savepoint_low(trx, savept);
168 trx_rollback_for_mysql_low(
181 trx_rollback_to_savepoint_low(trx, NULL);
206 switch (trx->
state) {
207 case TRX_STATE_NOT_STARTED:
208 ut_ad(trx->in_mysql_trx_list);
211 case TRX_STATE_ACTIVE:
212 ut_ad(trx->in_mysql_trx_list);
214 return(trx_rollback_for_mysql_low(trx));
216 case TRX_STATE_PREPARED:
218 return(trx_rollback_for_mysql_low(trx));
220 case TRX_STATE_COMMITTED_IN_MEMORY:
244 ut_ad(trx->in_mysql_trx_list);
246 switch (trx->
state) {
247 case TRX_STATE_NOT_STARTED:
249 case TRX_STATE_ACTIVE:
252 trx->
op_info =
"rollback of SQL statement";
268 case TRX_STATE_PREPARED:
269 case TRX_STATE_COMMITTED_IN_MEMORY:
307 trx_roll_savepoint_free(
327 while (savep != NULL) {
332 trx_roll_savepoint_free(trx, savep);
347 static __attribute__((nonnull, warn_unused_result))
349 trx_rollback_to_savepoint_for_mysql_low(
353 ib_int64_t* mysql_binlog_cache_pos)
364 ut_ad(trx->in_mysql_trx_list);
373 trx->op_info =
"rollback to a savepoint";
402 const char* savepoint_name,
403 ib_int64_t* mysql_binlog_cache_pos)
416 ut_ad(trx->in_mysql_trx_list);
418 savep = trx_savepoint_find(trx, savepoint_name);
424 switch (trx->
state) {
425 case TRX_STATE_NOT_STARTED:
427 fputs(
" InnoDB: Error: transaction has a savepoint ", stderr);
429 fputs(
" though it is not started\n", stderr);
431 case TRX_STATE_ACTIVE:
432 return(trx_rollback_to_savepoint_for_mysql_low(
433 trx, savep, mysql_binlog_cache_pos));
434 case TRX_STATE_PREPARED:
435 case TRX_STATE_COMMITTED_IN_MEMORY:
456 const char* savepoint_name,
457 ib_int64_t binlog_cache_pos)
464 trx_start_if_not_started_xa(trx);
466 savep = trx_savepoint_find(trx, savepoint_name);
502 const char* savepoint_name)
507 ut_ad(trx->in_mysql_trx_list);
509 savep = trx_savepoint_find(trx, savepoint_name);
512 trx_roll_savepoint_free(trx, savep);
529 return(trx == trx_roll_crash_recv_trx);
561 ib_int64_t rows_to_undo;
562 const char* unit =
"";
563 ibool dictionary_locked = FALSE;
574 thr->
child = roll_node;
583 trx_roll_crash_recv_trx =
trx;
585 trx_roll_max_undo_no = trx->
undo_no;
587 trx_roll_progress_printed_pct = 0;
589 rows_to_undo = trx_roll_max_undo_no;
593 if (rows_to_undo > 1000000000) {
594 rows_to_undo = rows_to_undo / 1000000;
600 " InnoDB: Rolling back trx with id " TRX_ID_FMT ", %lu%s"
603 (ulong) rows_to_undo, unit);
606 row_mysql_lock_data_dictionary(trx);
607 dictionary_locked = TRUE;
648 "Dropping table '%s', with id " UINT64PF
" "
655 ut_a(err == DB_SUCCESS);
659 if (dictionary_locked) {
664 "Rollback of trx with id " TRX_ID_FMT " completed", trx->
id);
668 trx_roll_crash_recv_trx = NULL;
679 trx_rollback_resurrected(
702 case TRX_STATE_COMMITTED_IN_MEMORY:
705 "InnoDB: Cleaning up trx with id " TRX_ID_FMT "\n",
710 case TRX_STATE_ACTIVE:
713 trx_rollback_active(trx);
718 case TRX_STATE_PREPARED:
720 case TRX_STATE_NOT_STARTED:
751 "InnoDB: Starting in background the rollback"
752 " of uncommitted transactions\n");
776 if (trx_rollback_resurrected(trx, all)) {
786 }
while (trx != NULL);
791 " InnoDB: Rollback of non-prepared"
792 " transactions completed\n");
803 extern "C" UNIV_INTERN
807 void* arg __attribute__((unused)))
813 #ifdef UNIV_PFS_THREAD
814 pfs_register_thread(trx_rollback_clean_thread_key);
824 OS_THREAD_DUMMY_RETURN;
838 ulint sz =
sizeof(*arr) +
sizeof(*arr->
infos) * n_cells;
869 trx_undo_arr_store_info(
883 for (i = 0; i < arr->
n_cells; i++) {
901 if (cell->
undo_no == undo_no) {
904 stored_here->
in_use = FALSE;
915 if (n == n_used && stored_here) {
932 trx_undo_arr_remove_info(
939 for (i = 0; i < arr->
n_cells; i++) {
959 trx_undo_arr_get_biggest(
989 trx_roll_try_truncate(
1008 biggest = trx_undo_arr_get_biggest(arr);
1010 if (biggest >= limit) {
1012 limit = biggest + 1;
1017 trx_undo_truncate_end(trx, trx->
insert_undo, limit);
1021 trx_undo_truncate_end(trx, trx->
update_undo, limit);
1031 trx_roll_pop_top_rec(
1057 if (prev_rec == NULL) {
1063 if (prev_rec_page != undo_page) {
1073 return(undo_page + offset);
1109 mutex_enter(&rseg->
mutex);
1111 trx_roll_try_truncate(trx);
1113 mutex_exit(&rseg->
mutex);
1119 if (!ins_undo || ins_undo->
empty) {
1121 }
else if (!upd_undo || upd_undo->
empty) {
1134 mutex_enter(&(rseg->
mutex));
1136 trx_roll_try_truncate(trx);
1138 mutex_exit(&(rseg->
mutex));
1146 is_insert = (undo == ins_undo);
1153 undo_rec = trx_roll_pop_top_rec(trx, undo, &mtr);
1162 if (trx == trx_roll_crash_recv_trx && trx_roll_max_undo_no > 1000) {
1164 progress_pct = 100 - (ulint)
1165 ((undo_no * 100) / trx_roll_max_undo_no);
1166 if (progress_pct != trx_roll_progress_printed_pct) {
1167 if (trx_roll_progress_printed_pct == 0) {
1169 "\nInnoDB: Progress in percents:"
1170 " %lu", (ulong) progress_pct);
1173 " %lu", (ulong) progress_pct);
1176 trx_roll_progress_printed_pct = progress_pct;
1182 if (!trx_undo_arr_store_info(trx, undo_no)) {
1198 return(undo_rec_copy);
1217 ret = trx_undo_arr_store_info(trx, undo_no);
1239 trx_undo_arr_remove_info(arr, undo_no);
1252 trx_roll_graph_build(
1307 roll_graph = trx_roll_graph_build(trx);
1309 trx->
graph = roll_graph;
1320 trx_rollback_finish(
1372 ib_id_t roll_limit = 0;
1386 node->
undo_thr = trx_rollback_start(trx, roll_limit);