~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: lbieber
  • Date: 2010-10-06 16:34:16 UTC
  • mfrom: (1816.1.3 build)
  • Revision ID: lbieber@orisndriz08-20101006163416-ea0sl59qgpglk21y
Merge Monty - Change the requirement from either libinnodb to libhaildb. Also, tied it to version 2.2
Merge Andrew - fix bug 650935: remove --compress from all clients
Merge Andrew - fix bug 653471: Add -A to drizzle client
Merge Travis - 621861 = To change C structs to C++ classes in Drizzle

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 1996, 2010, 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
51
51
the kernel mutex */
52
52
UNIV_INTERN ulint       trx_n_mysql_transactions = 0;
53
53
 
54
 
#ifdef UNIV_PFS_MUTEX
55
 
/* Key to register the mutex with performance schema */
56
 
UNIV_INTERN mysql_pfs_key_t     trx_undo_mutex_key;
57
 
#endif /* UNIV_PFS_MUTEX */
58
 
 
59
54
/*************************************************************//**
60
55
Set detailed error message for the transaction. */
61
56
UNIV_INTERN
96
91
        ut_ad(mutex_own(&kernel_mutex));
97
92
        ut_ad(sess);
98
93
 
99
 
        trx = static_cast<trx_t *>(mem_alloc(sizeof(trx_t)));
 
94
        trx = mem_alloc(sizeof(trx_t));
100
95
 
101
96
        trx->magic_n = TRX_MAGIC_N;
102
97
 
109
104
 
110
105
        trx->isolation_level = TRX_ISO_REPEATABLE_READ;
111
106
 
112
 
        trx->id = 0;
113
 
        trx->no = IB_ULONGLONG_MAX;
 
107
        trx->id = ut_dulint_zero;
 
108
        trx->no = ut_dulint_max;
114
109
 
115
110
        trx->support_xa = TRUE;
116
111
 
121
116
        trx->must_flush_log_later = FALSE;
122
117
 
123
118
        trx->dict_operation = TRX_DICT_OP_NONE;
124
 
        trx->table_id = 0;
 
119
        trx->table_id = ut_dulint_zero;
125
120
 
126
121
        trx->mysql_thd = NULL;
 
122
        trx->mysql_query_str = NULL;
127
123
        trx->duplicates = 0;
128
124
 
129
125
        trx->mysql_n_tables_locked = 0;
131
127
        trx->mysql_log_file_name = NULL;
132
128
        trx->mysql_log_offset = 0;
133
129
 
134
 
        mutex_create(trx_undo_mutex_key, &trx->undo_mutex, SYNC_TRX_UNDO);
 
130
        mutex_create(&trx->undo_mutex, SYNC_TRX_UNDO);
135
131
 
136
132
        trx->rseg = NULL;
137
133
 
138
 
        trx->undo_no = 0;
139
 
        trx->last_sql_stat_start.least_undo_no = 0;
 
134
        trx->undo_no = ut_dulint_zero;
 
135
        trx->last_sql_stat_start.least_undo_no = ut_dulint_zero;
140
136
        trx->insert_undo = NULL;
141
137
        trx->update_undo = NULL;
142
138
        trx->undo_no_arr = NULL;
186
182
        trx->autoinc_locks = ib_vector_create(
187
183
                mem_heap_create(sizeof(ib_vector_t) + sizeof(void*) * 4), 4);
188
184
 
189
 
        trx->log_commit_id= FALSE;
190
 
 
191
185
        return(trx);
192
186
}
193
187
 
389
383
        trx2 = UT_LIST_GET_FIRST(trx_sys->trx_list);
390
384
 
391
385
        while (trx2 != NULL) {
392
 
                if (trx->id >= trx2->id) {
 
386
                if (ut_dulint_cmp(trx->id, trx2->id) >= 0) {
393
387
 
394
 
                        ut_ad(trx->id > trx2->id);
 
388
                        ut_ad(ut_dulint_cmp(trx->id, trx2->id) == 1);
395
389
                        break;
396
390
                }
397
391
                trx2 = UT_LIST_GET_NEXT(trx_list, trx2);
426
420
        trx_undo_t*     undo;
427
421
        trx_t*          trx;
428
422
 
429
 
        ut_ad(mutex_own(&kernel_mutex));
430
423
        UT_LIST_INIT(trx_sys->trx_list);
431
424
 
432
425
        /* Look from the rollback segments if there exist undo logs for
460
453
                                                TRX_ID_FMT
461
454
                                                " was in the"
462
455
                                                " XA prepared state.\n",
463
 
                                                trx->id);
 
456
                                                TRX_ID_PREP_PRINTF(trx->id));
464
457
 
465
458
                                        if (srv_force_recovery == 0) {
466
459
 
492
485
                                trx->conc_state = TRX_ACTIVE;
493
486
 
494
487
                                /* A running transaction always has the number
495
 
                                field inited to IB_ULONGLONG_MAX */
 
488
                                field inited to ut_dulint_max */
496
489
 
497
 
                                trx->no = IB_ULONGLONG_MAX;
 
490
                                trx->no = ut_dulint_max;
498
491
                        }
499
492
 
500
493
                        if (undo->dict_operation) {
504
497
                        }
505
498
 
506
499
                        if (!undo->empty) {
507
 
                                trx->undo_no = undo->top_undo_no + 1;
 
500
                                trx->undo_no = ut_dulint_add(undo->top_undo_no,
 
501
                                                             1);
508
502
                        }
509
503
 
510
504
                        trx_list_insert_ordered(trx);
535
529
                                                        "InnoDB: Transaction "
536
530
                                                        TRX_ID_FMT " was in the"
537
531
                                                        " XA prepared state.\n",
538
 
                                                        trx->id);
 
532
                                                        TRX_ID_PREP_PRINTF(
 
533
                                                                trx->id));
539
534
 
540
535
                                                if (srv_force_recovery == 0) {
541
536
 
566
561
 
567
562
                                        /* A running transaction always has
568
563
                                        the number field inited to
569
 
                                        IB_ULONGLONG_MAX */
 
564
                                        ut_dulint_max */
570
565
 
571
 
                                        trx->no = IB_ULONGLONG_MAX;
 
566
                                        trx->no = ut_dulint_max;
572
567
                                }
573
568
 
574
569
                                trx->rseg = rseg;
584
579
                        trx->update_undo = undo;
585
580
 
586
581
                        if ((!undo->empty)
587
 
                            && undo->top_undo_no >= trx->undo_no) {
 
582
                            && (ut_dulint_cmp(undo->top_undo_no,
 
583
                                              trx->undo_no) >= 0)) {
588
584
 
589
 
                                trx->undo_no = undo->top_undo_no + 1;
 
585
                                trx->undo_no = ut_dulint_add(undo->top_undo_no,
 
586
                                                             1);
590
587
                        }
591
588
 
592
589
                        undo = UT_LIST_GET_NEXT(undo_list, undo);
648
645
        ut_ad(trx->rseg == NULL);
649
646
 
650
647
        if (trx->is_purge) {
651
 
                trx->id = 0;
 
648
                trx->id = ut_dulint_zero;
652
649
                trx->conc_state = TRX_ACTIVE;
653
650
                trx->start_time = time(NULL);
654
651
 
666
663
 
667
664
        trx->id = trx_sys_get_new_trx_id();
668
665
 
669
 
        /* The initial value for trx->no: IB_ULONGLONG_MAX is used in
 
666
        /* The initial value for trx->no: ut_dulint_max is used in
670
667
        read_view_open_now: */
671
668
 
672
 
        trx->no = IB_ULONGLONG_MAX;
 
669
        trx->no = ut_dulint_max;
673
670
 
674
671
        trx->rseg = rseg;
675
672
 
747
744
                mutex_enter(&(rseg->mutex));
748
745
 
749
746
                if (trx->insert_undo != NULL) {
750
 
                        trx_undo_set_state_at_finish(trx->insert_undo, &mtr);
 
747
                        trx_undo_set_state_at_finish(
 
748
                                rseg, trx, trx->insert_undo, &mtr);
751
749
                }
752
750
 
753
751
                undo = trx->update_undo;
755
753
                if (undo) {
756
754
                        mutex_enter(&kernel_mutex);
757
755
                        trx->no = trx_sys_get_new_trx_no();
 
756
 
758
757
                        mutex_exit(&kernel_mutex);
759
758
 
760
759
                        /* It is not necessary to obtain trx->undo_mutex here
762
761
                        transaction commit for this transaction. */
763
762
 
764
763
                        update_hdr_page = trx_undo_set_state_at_finish(
765
 
                                undo, &mtr);
 
764
                                rseg, trx, undo, &mtr);
766
765
 
767
766
                        /* We have to do the cleanup for the update log while
768
767
                        holding the rseg mutex because update log headers
774
773
 
775
774
                mutex_exit(&(rseg->mutex));
776
775
 
777
 
                /* Update the highest commit id currently in the system */
778
 
                if (trx_log_commit_id(trx))
779
 
                {
780
 
                        mutex_enter(&commit_id_mutex);
781
 
                        trx_sys_flush_commit_id(trx_sys_commit_id,
782
 
                                                TRX_SYS_DRIZZLE_LOG_INFO,
783
 
                                                &mtr);
784
 
                        mutex_exit(&commit_id_mutex);
 
776
                /* Update the latest MySQL binlog name and offset info
 
777
                in trx sys header if MySQL binlogging is on or the database
 
778
                server is a MySQL replication slave */
 
779
 
 
780
                if (trx->mysql_log_file_name
 
781
                    && trx->mysql_log_file_name[0] != '\0') {
 
782
                        trx_sys_update_mysql_binlog_offset(
 
783
                                trx->mysql_log_file_name,
 
784
                                trx->mysql_log_offset,
 
785
                                TRX_SYS_MYSQL_LOG_INFO, &mtr);
 
786
                        trx->mysql_log_file_name = NULL;
785
787
                }
786
788
 
787
789
                /* The following call commits the mini-transaction, making the
796
798
                in exactly the same order as commit lsn's, if the transactions
797
799
                have different rollback segments. To get exactly the same
798
800
                order we should hold the kernel mutex up to this point,
799
 
                adding to the contention of the kernel mutex. However, if
 
801
                adding to to the contention of the kernel mutex. However, if
800
802
                a transaction T2 is able to see modifications made by
801
803
                a transaction T1, T2 will always get a bigger transaction
802
804
                number and a bigger commit lsn than T1. */
835
837
        recovery i.e.: back ground rollback thread is still active
836
838
        then there is a chance that the rollback thread may see
837
839
        this trx as COMMITTED_IN_MEMORY and goes adhead to clean it
838
 
        up calling trx_cleanup_at_db_startup(). This can happen
 
840
        up calling trx_cleanup_at_db_startup(). This can happen 
839
841
        in the case we are committing a trx here that is left in
840
842
        PREPARED state during the crash. Note that commit of the
841
843
        rollback of a PREPARED trx happens in the recovery thread
930
932
 
931
933
        trx->conc_state = TRX_NOT_STARTED;
932
934
        trx->rseg = NULL;
933
 
        trx->undo_no = 0;
934
 
        trx->last_sql_stat_start.least_undo_no = 0;
 
935
        trx->undo_no = ut_dulint_zero;
 
936
        trx->last_sql_stat_start.least_undo_no = ut_dulint_zero;
 
937
        trx->mysql_query_str = NULL;
935
938
 
936
939
        ut_ad(UT_LIST_GET_LEN(trx->wait_thrs) == 0);
937
940
        ut_ad(UT_LIST_GET_LEN(trx->trx_locks) == 0);
942
945
/****************************************************************//**
943
946
Cleans up a transaction at database startup. The cleanup is needed if
944
947
the transaction already got to the middle of a commit when the database
945
 
crashed, and we cannot roll it back. */
 
948
crashed, andf we cannot roll it back. */
946
949
UNIV_INTERN
947
950
void
948
951
trx_cleanup_at_db_startup(
956
959
 
957
960
        trx->conc_state = TRX_NOT_STARTED;
958
961
        trx->rseg = NULL;
959
 
        trx->undo_no = 0;
960
 
        trx->last_sql_stat_start.least_undo_no = 0;
 
962
        trx->undo_no = ut_dulint_zero;
 
963
        trx->last_sql_stat_start.least_undo_no = ut_dulint_zero;
961
964
 
962
965
        UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx);
963
966
}
1242
1245
                /* It might be that the 'sig' slot is unused also in this
1243
1246
                case, but we choose the easy way of using mem_alloc */
1244
1247
 
1245
 
          sig = static_cast<trx_sig_t *>(mem_alloc(sizeof(trx_sig_t)));
 
1248
                sig = mem_alloc(sizeof(trx_sig_t));
1246
1249
        }
1247
1250
 
1248
1251
        UT_LIST_ADD_LAST(signals, trx->signals, sig);
1477
1480
{
1478
1481
        commit_node_t*  node;
1479
1482
 
1480
 
        node = static_cast<commit_node_t *>(mem_heap_alloc(heap, sizeof(commit_node_t)));
 
1483
        node = mem_heap_alloc(heap, sizeof(commit_node_t));
1481
1484
        node->common.type  = QUE_NODE_COMMIT;
1482
1485
        node->state = COMMIT_NODE_SEND;
1483
1486
 
1496
1499
        commit_node_t*  node;
1497
1500
        que_thr_t*      next_thr;
1498
1501
 
1499
 
        node = static_cast<commit_node_t *>(thr->run_node);
 
1502
        node = thr->run_node;
1500
1503
 
1501
1504
        ut_ad(que_node_get_type(node) == QUE_NODE_COMMIT);
1502
1505
 
1620
1623
        ut_a(trx);
1621
1624
 
1622
1625
        if (trx->conc_state == TRX_NOT_STARTED) {
1623
 
                trx->undo_no = 0;
 
1626
                trx->undo_no = ut_dulint_zero;
1624
1627
        }
1625
1628
 
1626
1629
        trx->last_sql_stat_start.least_undo_no = trx->undo_no;
1628
1631
 
1629
1632
/**********************************************************************//**
1630
1633
Prints info about a transaction to the given file. The caller must own the
1631
 
kernel mutex. */
 
1634
kernel mutex and must have called
 
1635
innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL
 
1636
or InnoDB cannot meanwhile change the info printed here. */
1632
1637
UNIV_INTERN
1633
1638
void
1634
1639
trx_print(
1640
1645
{
1641
1646
        ibool   newline;
1642
1647
 
1643
 
        fprintf(f, "TRANSACTION " TRX_ID_FMT, trx->id);
 
1648
        fprintf(f, "TRANSACTION " TRX_ID_FMT, TRX_ID_PREP_PRINTF(trx->id));
1644
1649
 
1645
1650
        switch (trx->conc_state) {
1646
1651
        case TRX_NOT_STARTED:
1723
1728
                fputs(", holds adaptive hash latch", f);
1724
1729
        }
1725
1730
 
1726
 
        if (trx->undo_no != 0) {
 
1731
        if (!ut_dulint_is_zero(trx->undo_no)) {
1727
1732
                newline = TRUE;
1728
 
                fprintf(f, ", undo log entries %llu",
1729
 
                        (ullint) trx->undo_no);
 
1733
                fprintf(f, ", undo log entries %lu",
 
1734
                        (ulong) ut_dulint_get_low(trx->undo_no));
1730
1735
        }
1731
1736
 
1732
1737
        if (newline) {
1742
1747
Compares the "weight" (or size) of two transactions. Transactions that
1743
1748
have edited non-transactional tables are considered heavier than ones
1744
1749
that have not.
1745
 
@return TRUE if weight(a) >= weight(b) */
 
1750
@return <0, 0 or >0; similar to strcmp(3) */
1746
1751
UNIV_INTERN
1747
 
ibool
1748
 
trx_weight_ge(
1749
 
/*==========*/
 
1752
int
 
1753
trx_weight_cmp(
 
1754
/*===========*/
1750
1755
        const trx_t*    a,      /*!< in: the first transaction to be compared */
1751
1756
        const trx_t*    b)      /*!< in: the second transaction to be compared */
1752
1757
{
1757
1762
        not edited non-transactional tables. */
1758
1763
 
1759
1764
        a_notrans_edit = a->mysql_thd != NULL
1760
 
                && thd_has_edited_nontrans_tables(a->mysql_thd);
 
1765
            && thd_has_edited_nontrans_tables(a->mysql_thd);
1761
1766
 
1762
1767
        b_notrans_edit = b->mysql_thd != NULL
1763
 
                && thd_has_edited_nontrans_tables(b->mysql_thd);
1764
 
 
1765
 
        if (a_notrans_edit != b_notrans_edit) {
1766
 
 
1767
 
                return(a_notrans_edit);
 
1768
            && thd_has_edited_nontrans_tables(b->mysql_thd);
 
1769
 
 
1770
        if (a_notrans_edit && !b_notrans_edit) {
 
1771
 
 
1772
                return(1);
 
1773
        }
 
1774
 
 
1775
        if (!a_notrans_edit && b_notrans_edit) {
 
1776
 
 
1777
                return(-1);
1768
1778
        }
1769
1779
 
1770
1780
        /* Either both had edited non-transactional tables or both had
1775
1785
        fprintf(stderr,
1776
1786
                "%s TRX_WEIGHT(a): %lld+%lu, TRX_WEIGHT(b): %lld+%lu\n",
1777
1787
                __func__,
1778
 
                a->undo_no, UT_LIST_GET_LEN(a->trx_locks),
1779
 
                b->undo_no, UT_LIST_GET_LEN(b->trx_locks));
 
1788
                ut_conv_dulint_to_longlong(a->undo_no),
 
1789
                UT_LIST_GET_LEN(a->trx_locks),
 
1790
                ut_conv_dulint_to_longlong(b->undo_no),
 
1791
                UT_LIST_GET_LEN(b->trx_locks));
1780
1792
#endif
1781
1793
 
1782
 
        return(TRX_WEIGHT(a) >= TRX_WEIGHT(b));
 
1794
        return(ut_dulint_cmp(TRX_WEIGHT(a), TRX_WEIGHT(b)));
1783
1795
}
1784
1796
 
1785
1797
/****************************************************************//**
1790
1802
/*===================*/
1791
1803
        trx_t*  trx)    /*!< in: transaction */
1792
1804
{
 
1805
        page_t*         update_hdr_page;
1793
1806
        trx_rseg_t*     rseg;
1794
1807
        ib_uint64_t     lsn             = 0;
1795
1808
        mtr_t           mtr;
1822
1835
                }
1823
1836
 
1824
1837
                if (trx->update_undo) {
1825
 
                        trx_undo_set_state_at_prepare(
 
1838
                        update_hdr_page = trx_undo_set_state_at_prepare(
1826
1839
                                trx, trx->update_undo, &mtr);
1827
1840
                }
1828
1841
 
1960
1973
                        fprintf(stderr,
1961
1974
                                "  InnoDB: Transaction " TRX_ID_FMT " in"
1962
1975
                                " prepared state after recovery\n",
1963
 
                                trx->id);
 
1976
                                TRX_ID_PREP_PRINTF(trx->id));
1964
1977
 
1965
1978
                        ut_print_timestamp(stderr);
1966
1979
                        fprintf(stderr,
1967
1980
                                "  InnoDB: Transaction contains changes"
1968
 
                                " to %llu rows\n",
1969
 
                                (ullint) trx->undo_no);
 
1981
                                " to %lu rows\n",
 
1982
                                (ulong) ut_conv_dulint_to_longlong(
 
1983
                                        trx->undo_no));
1970
1984
 
1971
1985
                        count++;
1972
1986
 
2015
2029
        while (trx) {
2016
2030
                /* Compare two X/Open XA transaction id's: their
2017
2031
                length should be the same and binary comparison
2018
 
                of gtrid_length+bqual_length bytes should be
 
2032
                of gtrid_lenght+bqual_length bytes should be
2019
2033
                the same */
2020
2034
 
2021
2035
                if (xid->gtrid_length == trx->xid.gtrid_length