~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/trx/trx0roll.c

  • Committer: Lee Bieber
  • Date: 2010-11-07 19:34:48 UTC
  • mfrom: (1910.1.2 build)
  • Revision ID: kalebral@gmail.com-20101107193448-64kdu912qej354sh
Merge Stewart - including adapting and expanding the "differences from mysql" page from the wiki.
Merge Stewart - fix bug 668143: drizzleslap with --commit runs second iteration data load in a transaction

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 1996, 2009, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
37
37
#include "trx0rec.h"
38
38
#include "que0que.h"
39
39
#include "usr0sess.h"
 
40
#include "srv0que.h"
40
41
#include "srv0start.h"
41
42
#include "row0undo.h"
42
43
#include "row0mysql.h"
52
53
 
53
54
/** In crash recovery we set this to the undo n:o of the current trx to be
54
55
rolled back. Then we can print how many % the rollback has progressed. */
55
 
static undo_no_t        trx_roll_max_undo_no;
 
56
static ib_int64_t       trx_roll_max_undo_no;
56
57
 
57
58
/** Auxiliary variable which tells the previous progress % we printed */
58
59
static ulint            trx_roll_progress_printed_pct;
93
94
 
94
95
        thr = pars_complete_graph_for_exec(roll_node, trx, heap);
95
96
 
96
 
        ut_a(thr == que_fork_start_command(static_cast<que_fork_t *>(que_node_get_parent(thr))));
 
97
        ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
97
98
        que_run_threads(thr);
98
99
 
99
100
        mutex_enter(&kernel_mutex);
336
337
 
337
338
        /* Create a new savepoint and add it as the last in the list */
338
339
 
339
 
        savep = static_cast<trx_named_savept_t *>(mem_alloc(sizeof(trx_named_savept_t)));
 
340
        savep = mem_alloc(sizeof(trx_named_savept_t));
340
341
 
341
342
        savep->name = mem_strdup(savepoint_name);
342
343
 
443
444
        ut_a(thr == que_fork_start_command(fork));
444
445
 
445
446
        trx_roll_crash_recv_trx = trx;
446
 
        trx_roll_max_undo_no = trx->undo_no;
 
447
        trx_roll_max_undo_no = ut_conv_dulint_to_longlong(trx->undo_no);
447
448
        trx_roll_progress_printed_pct = 0;
448
449
        rows_to_undo = trx_roll_max_undo_no;
449
450
 
456
457
        fprintf(stderr,
457
458
                "  InnoDB: Rolling back trx with id " TRX_ID_FMT ", %lu%s"
458
459
                " rows to undo\n",
459
 
                trx->id,
 
460
                TRX_ID_PREP_PRINTF(trx->id),
460
461
                (ulong) rows_to_undo, unit);
461
462
        mutex_exit(&kernel_mutex);
462
463
 
478
479
                mutex_exit(&kernel_mutex);
479
480
 
480
481
                fprintf(stderr,
481
 
                        "InnoDB: Waiting for rollback of trx id "
482
 
                        TRX_ID_FMT " to end\n",
483
 
                        trx->id);
 
482
                        "InnoDB: Waiting for rollback of trx id %lu to end\n",
 
483
                        (ulong) ut_dulint_get_low(trx->id));
484
484
                os_thread_sleep(100000);
485
485
 
486
486
                mutex_enter(&kernel_mutex);
489
489
        mutex_exit(&kernel_mutex);
490
490
 
491
491
        if (trx_get_dict_operation(trx) != TRX_DICT_OP_NONE
492
 
            && trx->table_id != 0) {
 
492
            && !ut_dulint_is_zero(trx->table_id)) {
493
493
 
494
494
                /* If the transaction was for a dictionary operation, we
495
495
                drop the relevant table, if it still exists */
496
496
 
497
497
                fprintf(stderr,
498
 
                        "InnoDB: Dropping table with id %llu"
 
498
                        "InnoDB: Dropping table with id %lu %lu"
499
499
                        " in recovery if it exists\n",
500
 
                        (ullint) trx->table_id);
 
500
                        (ulong) ut_dulint_get_high(trx->table_id),
 
501
                        (ulong) ut_dulint_get_low(trx->table_id));
501
502
 
502
503
                table = dict_table_get_on_id_low(trx->table_id);
503
504
 
521
522
 
522
523
        fprintf(stderr, "\nInnoDB: Rolling back of trx id " TRX_ID_FMT
523
524
                " completed\n",
524
 
                trx->id);
 
525
                TRX_ID_PREP_PRINTF(trx->id));
525
526
        mem_heap_free(heap);
526
527
 
527
528
        trx_roll_crash_recv_trx = NULL;
574
575
                        fprintf(stderr,
575
576
                                "InnoDB: Cleaning up trx with id "
576
577
                                TRX_ID_FMT "\n",
577
 
                                trx->id);
 
578
                                TRX_ID_PREP_PRINTF(trx->id));
578
579
                        trx_cleanup_at_db_startup(trx);
579
580
                        goto loop;
580
581
 
610
611
os_thread_ret_t
611
612
trx_rollback_or_clean_all_recovered(
612
613
/*================================*/
613
 
        void*   /*arg*/)
 
614
        void*   arg __attribute__((unused)))
614
615
                        /*!< in: a dummy parameter required by
615
616
                        os_thread_create */
616
617
{
617
 
#ifdef UNIV_PFS_THREAD
618
 
        pfs_register_thread(trx_rollback_clean_thread_key);
619
 
#endif /* UNIV_PFS_THREAD */
620
 
 
621
618
        trx_rollback_or_clean_recovered(TRUE);
622
619
 
623
620
        /* We count the number of threads in os_thread_exit(). A created
642
639
 
643
640
        heap = mem_heap_create(1024);
644
641
 
645
 
        arr = static_cast<trx_undo_arr_t *>(mem_heap_alloc(heap, sizeof(trx_undo_arr_t)));
 
642
        arr = mem_heap_alloc(heap, sizeof(trx_undo_arr_t));
646
643
 
647
 
        arr->infos = static_cast<trx_undo_inf_t *>(mem_heap_alloc(heap, sizeof(trx_undo_inf_t)
648
 
                                                                  * UNIV_MAX_PARALLELISM));
 
644
        arr->infos = mem_heap_alloc(heap, sizeof(trx_undo_inf_t)
 
645
                                    * UNIV_MAX_PARALLELISM);
649
646
        arr->n_cells = UNIV_MAX_PARALLELISM;
650
647
        arr->n_used = 0;
651
648
 
710
707
                } else {
711
708
                        n++;
712
709
 
713
 
                        if (cell->undo_no == undo_no) {
 
710
                        if (0 == ut_dulint_cmp(cell->undo_no, undo_no)) {
714
711
 
715
712
                                if (stored_here) {
716
713
                                        stored_here->in_use = FALSE;
743
740
        undo_no_t       undo_no)/*!< in: undo number */
744
741
{
745
742
        trx_undo_inf_t* cell;
 
743
        ulint           n_used;
 
744
        ulint           n;
746
745
        ulint           i;
747
746
 
 
747
        n_used = arr->n_used;
 
748
        n = 0;
 
749
 
748
750
        for (i = 0;; i++) {
749
751
                cell = trx_undo_arr_get_nth_info(arr, i);
750
752
 
751
753
                if (cell->in_use
752
 
                    && cell->undo_no == undo_no) {
 
754
                    && 0 == ut_dulint_cmp(cell->undo_no, undo_no)) {
753
755
 
754
756
                        cell->in_use = FALSE;
755
757
 
764
766
 
765
767
/*******************************************************************//**
766
768
Gets the biggest undo number in an array.
767
 
@return biggest value, 0 if the array is empty */
 
769
@return biggest value, ut_dulint_zero if the array is empty */
768
770
static
769
771
undo_no_t
770
772
trx_undo_arr_get_biggest(
779
781
 
780
782
        n = 0;
781
783
        n_used = arr->n_used;
782
 
        biggest = 0;
 
784
        biggest = ut_dulint_zero;
783
785
 
784
786
        for (i = 0;; i++) {
785
787
                cell = trx_undo_arr_get_nth_info(arr, i);
786
788
 
787
789
                if (cell->in_use) {
788
790
                        n++;
789
 
                        if (cell->undo_no > biggest) {
 
791
                        if (ut_dulint_cmp(cell->undo_no, biggest) > 0) {
790
792
 
791
793
                                biggest = cell->undo_no;
792
794
                        }
822
824
        if (arr->n_used > 0) {
823
825
                biggest = trx_undo_arr_get_biggest(arr);
824
826
 
825
 
                if (biggest >= limit) {
 
827
                if (ut_dulint_cmp(biggest, limit) >= 0) {
826
828
 
827
 
                        limit = biggest + 1;
 
829
                        limit = ut_dulint_add(biggest, 1);
828
830
                }
829
831
        }
830
832
 
860
862
                                                undo->top_page_no, mtr);
861
863
        offset = undo->top_offset;
862
864
 
863
 
        /*      fprintf(stderr, "Thread %lu undoing trx " TRX_ID_FMT
864
 
                        " undo record " TRX_ID_FMT "\n",
865
 
        os_thread_get_curr_id(), trx->id, undo->top_undo_no); */
 
865
        /*      fprintf(stderr, "Thread %lu undoing trx %lu undo record %lu\n",
 
866
        os_thread_get_curr_id(), ut_dulint_get_low(trx->id),
 
867
        ut_dulint_get_low(undo->top_undo_no)); */
866
868
 
867
869
        prev_rec = trx_undo_get_prev_rec(undo_page + offset,
868
870
                                         undo->hdr_page_no, undo->hdr_offset,
933
935
                undo = upd_undo;
934
936
        } else if (!upd_undo || upd_undo->empty) {
935
937
                undo = ins_undo;
936
 
        } else if (upd_undo->top_undo_no > ins_undo->top_undo_no) {
 
938
        } else if (ut_dulint_cmp(upd_undo->top_undo_no,
 
939
                                 ins_undo->top_undo_no) > 0) {
937
940
                undo = upd_undo;
938
941
        } else {
939
942
                undo = ins_undo;
940
943
        }
941
944
 
942
945
        if (!undo || undo->empty
943
 
            || limit > undo->top_undo_no) {
 
946
            || (ut_dulint_cmp(limit, undo->top_undo_no) > 0)) {
944
947
 
945
948
                if ((trx->undo_no_arr)->n_used == 0) {
946
949
                        /* Rollback is ending */
972
975
 
973
976
        undo_no = trx_undo_rec_get_undo_no(undo_rec);
974
977
 
975
 
        ut_ad(undo_no + 1 == trx->undo_no);
 
978
        ut_ad(ut_dulint_cmp(ut_dulint_add(undo_no, 1), trx->undo_no) == 0);
976
979
 
977
980
        /* We print rollback progress info if we are in a crash recovery
978
981
        and the transaction has at least 1000 row operations to undo. */
980
983
        if (trx == trx_roll_crash_recv_trx && trx_roll_max_undo_no > 1000) {
981
984
 
982
985
                progress_pct = 100 - (ulint)
983
 
                        ((undo_no * 100) / trx_roll_max_undo_no);
 
986
                        ((ut_conv_dulint_to_longlong(undo_no) * 100)
 
987
                         / trx_roll_max_undo_no);
984
988
                if (progress_pct != trx_roll_progress_printed_pct) {
985
989
                        if (trx_roll_progress_printed_pct == 0) {
986
990
                                fprintf(stderr,
1083
1087
 
1084
1088
        /* Initialize the rollback field in the transaction */
1085
1089
 
1086
 
        switch (sig->type) {
1087
 
        case TRX_SIG_TOTAL_ROLLBACK:
1088
 
                trx->roll_limit = 0;
1089
 
                break;
1090
 
        case TRX_SIG_ROLLBACK_TO_SAVEPT:
 
1090
        if (sig->type == TRX_SIG_TOTAL_ROLLBACK) {
 
1091
 
 
1092
                trx->roll_limit = ut_dulint_zero;
 
1093
 
 
1094
        } else if (sig->type == TRX_SIG_ROLLBACK_TO_SAVEPT) {
 
1095
 
1091
1096
                trx->roll_limit = (sig->savept).least_undo_no;
1092
 
                break;
1093
 
        case TRX_SIG_ERROR_OCCURRED:
 
1097
 
 
1098
        } else if (sig->type == TRX_SIG_ERROR_OCCURRED) {
 
1099
 
1094
1100
                trx->roll_limit = trx->last_sql_stat_start.least_undo_no;
1095
 
                break;
1096
 
        default:
 
1101
        } else {
1097
1102
                ut_error;
1098
1103
        }
1099
1104
 
1100
 
        ut_a(trx->roll_limit <= trx->undo_no);
 
1105
        ut_a(ut_dulint_cmp(trx->roll_limit, trx->undo_no) <= 0);
1101
1106
 
1102
1107
        trx->pages_undone = 0;
1103
1108
 
1261
1266
 
1262
1267
#ifdef UNIV_DEBUG
1263
1268
        if (lock_print_waits) {
1264
 
                fprintf(stderr, "Trx " TRX_ID_FMT " rollback finished\n",
1265
 
                        trx->id);
 
1269
                fprintf(stderr, "Trx %lu rollback finished\n",
 
1270
                        (ulong) ut_dulint_get_low(trx->id));
1266
1271
        }
1267
1272
#endif /* UNIV_DEBUG */
1268
1273
 
1298
1303
{
1299
1304
        roll_node_t*    node;
1300
1305
 
1301
 
        
1302
 
        node = static_cast<roll_node_t *>(mem_heap_alloc(heap, sizeof(roll_node_t)));
 
1306
        node = mem_heap_alloc(heap, sizeof(roll_node_t));
1303
1307
        node->common.type = QUE_NODE_ROLLBACK;
1304
1308
        node->state = ROLL_NODE_SEND;
1305
1309
 
1321
1325
        ulint           sig_no;
1322
1326
        trx_savept_t*   savept;
1323
1327
 
1324
 
        node = static_cast<roll_node_t *>(thr->run_node);
 
1328
        node = thr->run_node;
1325
1329
 
1326
1330
        ut_ad(que_node_get_type(node) == QUE_NODE_ROLLBACK);
1327
1331