31
31
#define TRX_ROLL_TRUNC_THRESHOLD 1
33
33
/* In crash recovery, the current trx to be rolled back */
34
static trx_t* trx_roll_crash_recv_trx = NULL;
34
trx_t* trx_roll_crash_recv_trx = NULL;
36
36
/* In crash recovery we set this to the undo n:o of the current trx to be
37
37
rolled back. Then we can print how many % the rollback has progressed. */
38
static ib_int64_t trx_roll_max_undo_no;
38
ib_longlong trx_roll_max_undo_no;
40
40
/* Auxiliary variable which tells the previous progress % we printed */
41
static ulint trx_roll_progress_printed_pct;
41
ulint trx_roll_progress_printed_pct;
43
43
/***********************************************************************
44
44
Rollback a transaction used in MySQL. */
47
47
trx_general_rollback_for_mysql(
48
48
/*===========================*/
135
135
the transaction object does not have an InnoDB session object, and we
136
136
set a dummy session that we use for all MySQL transactions. */
138
mutex_enter(&kernel_mutex);
140
if (trx->sess == NULL) {
141
/* Open a dummy session */
143
if (!trx_dummy_sess) {
144
trx_dummy_sess = sess_open();
147
trx->sess = trx_dummy_sess;
150
mutex_exit(&kernel_mutex);
138
152
err = trx_general_rollback_for_mysql(trx, FALSE, NULL);
140
154
trx->op_info = "";
207
221
row holds a lock where the lock information is carried by the trx id stored in
208
222
the row, these locks are naturally released in the rollback. Savepoints which
209
223
were set after this savepoint are deleted. */
212
226
trx_rollback_to_savepoint_for_mysql(
213
227
/*================================*/
217
231
otherwise DB_SUCCESS */
218
232
trx_t* trx, /* in: transaction handle */
219
233
const char* savepoint_name, /* in: savepoint name */
220
ib_int64_t* mysql_binlog_cache_pos) /* out: the MySQL binlog cache
234
ib_longlong* mysql_binlog_cache_pos) /* out: the MySQL binlog cache
221
235
position corresponding to this
222
236
savepoint; MySQL needs this
223
237
information to remove the
275
289
If there is already a savepoint of the same name, this call erases that old
276
290
savepoint and replaces it with a new. Savepoints are deleted in a transaction
277
291
commit or rollback. */
280
294
trx_savepoint_for_mysql(
281
295
/*====================*/
282
296
/* out: always DB_SUCCESS */
283
297
trx_t* trx, /* in: transaction handle */
284
298
const char* savepoint_name, /* in: savepoint name */
285
ib_int64_t binlog_cache_pos) /* in: MySQL binlog cache
299
ib_longlong binlog_cache_pos) /* in: MySQL binlog cache
286
300
position corresponding to this
287
301
connection at the time of the
392
406
/***********************************************************************
393
Roll back an active transaction. */
398
trx_t* trx) /* in/out: transaction */
407
Rollback or clean up transactions which have no user session. If the
408
transaction already was committed, then we clean up a possible insert
409
undo log. If the transaction was not yet committed, then we roll it back.
410
Note: this is done in a background thread. */
413
trx_rollback_or_clean_all_without_sess(
414
/*===================================*/
415
/* out: a dummy parameter */
416
void* arg __attribute__((unused)))
417
/* in: a dummy parameter required by
400
420
mem_heap_t* heap;
401
421
que_fork_t* fork;
403
423
roll_node_t* roll_node;
404
425
dict_table_t* table;
405
ib_int64_t rows_to_undo;
426
ib_longlong rows_to_undo;
406
427
const char* unit = "";
407
ibool dictionary_locked = FALSE;
430
mutex_enter(&kernel_mutex);
432
/* Open a dummy session */
434
if (!trx_dummy_sess) {
435
trx_dummy_sess = sess_open();
438
mutex_exit(&kernel_mutex);
440
if (UT_LIST_GET_FIRST(trx_sys->trx_list)) {
443
"InnoDB: Starting in background the rollback"
444
" of uncommitted transactions\n");
409
449
heap = mem_heap_create(512);
451
mutex_enter(&kernel_mutex);
453
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
456
if ((trx->sess || (trx->conc_state == TRX_NOT_STARTED))) {
457
trx = UT_LIST_GET_NEXT(trx_list, trx);
458
} else if (trx->conc_state == TRX_PREPARED) {
460
trx->sess = trx_dummy_sess;
461
trx = UT_LIST_GET_NEXT(trx_list, trx);
467
mutex_exit(&kernel_mutex);
470
ut_print_timestamp(stderr);
472
" InnoDB: Rollback of non-prepared transactions"
480
trx->sess = trx_dummy_sess;
482
if (trx->conc_state == TRX_COMMITTED_IN_MEMORY) {
483
fprintf(stderr, "InnoDB: Cleaning up trx with id %lu %lu\n",
484
(ulong) ut_dulint_get_high(trx->id),
485
(ulong) ut_dulint_get_low(trx->id));
487
trx_cleanup_at_db_startup(trx);
411
494
fork = que_fork_create(NULL, NULL, QUE_FORK_RECOVERY, heap);
437
520
ut_print_timestamp(stderr);
439
" InnoDB: Rolling back trx with id " TRX_ID_FMT ", %lu%s"
522
" InnoDB: Rolling back trx with id %lu %lu, %lu%s"
440
523
" rows to undo\n",
441
TRX_ID_PREP_PRINTF(trx->id),
524
(ulong) ut_dulint_get_high(trx->id),
525
(ulong) ut_dulint_get_low(trx->id),
442
526
(ulong) rows_to_undo, unit);
443
527
mutex_exit(&kernel_mutex);
470
553
mutex_exit(&kernel_mutex);
472
if (trx_get_dict_operation(trx) != TRX_DICT_OP_NONE
473
&& !ut_dulint_is_zero(trx->table_id)) {
555
if (trx->dict_operation) {
475
556
/* If the transaction was for a dictionary operation, we
476
557
drop the relevant table, if it still exists */
484
565
table = dict_table_get_on_id_low(trx->table_id);
489
568
fputs("InnoDB: Table found: dropping table ", stderr);
490
569
ut_print_name(stderr, trx, TRUE, table->name);
491
570
fputs(" in recovery\n", stderr);
499
if (dictionary_locked) {
578
if (trx->dict_operation) {
500
579
row_mysql_unlock_data_dictionary(trx);
503
fprintf(stderr, "\nInnoDB: Rolling back of trx id " TRX_ID_FMT
505
TRX_ID_PREP_PRINTF(trx->id));
582
fprintf(stderr, "\nInnoDB: Rolling back of trx id %lu %lu completed\n",
583
(ulong) ut_dulint_get_high(trx->id),
584
(ulong) ut_dulint_get_low(trx->id));
506
585
mem_heap_free(heap);
508
587
trx_roll_crash_recv_trx = NULL;
511
/***********************************************************************
512
Rollback or clean up any incomplete transactions which were
513
encountered in crash recovery. If the transaction already was
514
committed, then we clean up a possible insert undo log. If the
515
transaction was not yet committed, then we roll it back.
516
Note: this is done in a background thread. */
519
trx_rollback_or_clean_all_recovered(
520
/*================================*/
521
/* out: a dummy parameter */
522
void* arg __attribute__((unused)))
523
/* in: a dummy parameter required by
528
mutex_enter(&kernel_mutex);
530
if (UT_LIST_GET_FIRST(trx_sys->trx_list)) {
533
"InnoDB: Starting in background the rollback"
534
" of uncommitted transactions\n");
539
mutex_exit(&kernel_mutex);
542
mutex_enter(&kernel_mutex);
544
for (trx = UT_LIST_GET_FIRST(trx_sys->trx_list); trx;
545
trx = UT_LIST_GET_NEXT(trx_list, trx)) {
546
if (!trx->is_recovered) {
550
switch (trx->conc_state) {
551
case TRX_NOT_STARTED:
555
case TRX_COMMITTED_IN_MEMORY:
556
mutex_exit(&kernel_mutex);
558
"InnoDB: Cleaning up trx with id "
560
TRX_ID_PREP_PRINTF(trx->id));
561
trx_cleanup_at_db_startup(trx);
565
mutex_exit(&kernel_mutex);
566
trx_rollback_active(trx);
571
ut_print_timestamp(stderr);
573
" InnoDB: Rollback of non-prepared transactions completed\n");
576
mutex_exit(&kernel_mutex);
578
592
/* We count the number of threads in os_thread_exit(). A created
579
593
thread should always use that to exit and not use return() to exit. */
833
847
undo->empty = TRUE;
835
prev_rec_page = page_align(prev_rec);
849
prev_rec_page = buf_frame_align(prev_rec);
837
851
if (prev_rec_page != undo_page) {
839
853
trx->pages_undone++;
842
undo->top_page_no = page_get_page_no(prev_rec_page);
856
undo->top_page_no = buf_frame_get_page_no(prev_rec_page);
843
857
undo->top_offset = prev_rec - prev_rec_page;
844
858
undo->top_undo_no = trx_undo_rec_get_undo_no(prev_rec);
853
867
undo number of the popped undo record to the array of currently processed
854
868
undo numbers in the transaction. When the query thread finishes processing
855
869
of this undo record, it must be released with trx_undo_rec_release. */
858
872
trx_roll_pop_top_rec_of_trx(
859
873
/*========================*/