~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2008-10-28 08:36:02 UTC
  • mfrom: (520.4.13 merge-innodb-plugin)
  • Revision ID: brian@tangent.org-20081028083602-0p3zzlhlxr5q2sqo
Merging Monty's work

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
#include "trx0xa.h"
28
28
#include "ha_prototypes.h"
29
29
 
30
 
/* Copy of the prototype for innobase_mysql_print_session: this
31
 
copy MUST be equal to the one in mysql/sql/ha_innodb.cc ! */
32
 
 
33
 
void innobase_mysql_print_session(
34
 
        FILE*   f,
35
 
        void*   session,
36
 
        ulint   max_query_len);
37
 
 
38
30
/* Dummy session used currently in MySQL interface */
39
 
sess_t*         trx_dummy_sess = NULL;
 
31
UNIV_INTERN sess_t*             trx_dummy_sess = NULL;
40
32
 
41
33
/* Number of transactions currently allocated for MySQL: protected by
42
34
the kernel mutex */
43
 
ulint   trx_n_mysql_transactions = 0;
44
 
 
45
 
/*****************************************************************
46
 
Starts the transaction if it is not yet started. */
47
 
 
48
 
void
49
 
trx_start_if_not_started_noninline(
50
 
/*===============================*/
51
 
        trx_t*  trx) /* in: transaction */
52
 
{
53
 
        trx_start_if_not_started(trx);
54
 
}
 
35
UNIV_INTERN ulint       trx_n_mysql_transactions = 0;
55
36
 
56
37
/*****************************************************************
57
38
Set detailed error message for the transaction. */
58
 
 
 
39
UNIV_INTERN
59
40
void
60
41
trx_set_detailed_error(
61
42
/*===================*/
68
49
/*****************************************************************
69
50
Set detailed error message for the transaction from a file. Note that the
70
51
file is rewinded before reading from it. */
71
 
 
 
52
UNIV_INTERN
72
53
void
73
54
trx_set_detailed_error_from_file(
74
55
/*=============================*/
80
61
}
81
62
 
82
63
/********************************************************************
83
 
Retrieves the error_info field from a trx. */
84
 
 
85
 
void*
86
 
trx_get_error_info(
87
 
/*===============*/
88
 
                        /* out: the error info */
89
 
        trx_t*  trx)    /* in: trx object */
90
 
{
91
 
        return(trx->error_info);
92
 
}
93
 
 
94
 
/********************************************************************
95
64
Creates and initializes a transaction object. */
96
 
 
 
65
UNIV_INTERN
97
66
trx_t*
98
67
trx_create(
99
68
/*=======*/
100
69
                        /* out, own: the transaction */
101
 
        sess_t* sess)   /* in: session or NULL */
 
70
        sess_t* sess)   /* in: session */
102
71
{
103
72
        trx_t*  trx;
104
73
 
105
74
        ut_ad(mutex_own(&kernel_mutex));
 
75
        ut_ad(sess);
106
76
 
107
77
        trx = mem_alloc(sizeof(trx_t));
108
78
 
111
81
        trx->op_info = "";
112
82
 
113
83
        trx->is_purge = 0;
 
84
        trx->is_recovered = 0;
114
85
        trx->conc_state = TRX_NOT_STARTED;
115
86
        trx->start_time = time(NULL);
116
87
 
127
98
        trx->flush_log_later = FALSE;
128
99
        trx->must_flush_log_later = FALSE;
129
100
 
130
 
        trx->dict_operation = FALSE;
 
101
        trx->dict_operation = TRX_DICT_OP_NONE;
 
102
        trx->table_id = ut_dulint_zero;
131
103
 
132
104
        trx->mysql_session = NULL;
133
105
        trx->mysql_query_str = NULL;
151
123
        trx->undo_no_arr = NULL;
152
124
 
153
125
        trx->error_state = DB_SUCCESS;
 
126
        trx->error_key_num = 0;
154
127
        trx->detailed_error[0] = '\0';
155
128
 
156
129
        trx->sess = sess;
199
172
 
200
173
/************************************************************************
201
174
Creates a transaction object for MySQL. */
202
 
 
 
175
UNIV_INTERN
203
176
trx_t*
204
177
trx_allocate_for_mysql(void)
205
178
/*========================*/
209
182
 
210
183
        mutex_enter(&kernel_mutex);
211
184
 
212
 
        /* Open a dummy session */
213
 
 
214
 
        if (!trx_dummy_sess) {
215
 
                trx_dummy_sess = sess_open();
216
 
        }
217
 
 
218
185
        trx = trx_create(trx_dummy_sess);
219
186
 
220
187
        trx_n_mysql_transactions++;
232
199
 
233
200
/************************************************************************
234
201
Creates a transaction object for background operations by the master thread. */
235
 
 
 
202
UNIV_INTERN
236
203
trx_t*
237
204
trx_allocate_for_background(void)
238
205
/*=============================*/
242
209
 
243
210
        mutex_enter(&kernel_mutex);
244
211
 
245
 
        /* Open a dummy session */
246
 
 
247
 
        if (!trx_dummy_sess) {
248
 
                trx_dummy_sess = sess_open();
249
 
        }
250
 
 
251
212
        trx = trx_create(trx_dummy_sess);
252
213
 
253
214
        mutex_exit(&kernel_mutex);
257
218
 
258
219
/************************************************************************
259
220
Releases the search latch if trx has reserved it. */
260
 
 
 
221
UNIV_INTERN
261
222
void
262
223
trx_search_latch_release_if_reserved(
263
224
/*=================================*/
272
233
 
273
234
/************************************************************************
274
235
Frees a transaction object. */
275
 
 
 
236
UNIV_INTERN
276
237
void
277
238
trx_free(
278
239
/*=====*/
350
311
 
351
312
/************************************************************************
352
313
Frees a transaction object for MySQL. */
353
 
 
 
314
UNIV_INTERN
354
315
void
355
316
trx_free_for_mysql(
356
317
/*===============*/
371
332
 
372
333
/************************************************************************
373
334
Frees a transaction object of a background operation of the master thread. */
374
 
 
 
335
UNIV_INTERN
375
336
void
376
337
trx_free_for_background(
377
338
/*====================*/
430
391
already exist when this function is called, because the lists of
431
392
transactions to be rolled back or cleaned up are built based on the
432
393
undo log lists. */
433
 
 
 
394
UNIV_INTERN
434
395
void
435
396
trx_lists_init_at_db_start(void)
436
397
/*============================*/
451
412
 
452
413
                while (undo != NULL) {
453
414
 
454
 
                        trx = trx_create(NULL);
 
415
                        trx = trx_create(trx_dummy_sess);
455
416
 
 
417
                        trx->is_recovered = TRUE;
456
418
                        trx->id = undo->trx_id;
457
419
                        trx->xid = undo->xid;
458
420
                        trx->insert_undo = undo;
467
429
                                if (undo->state == TRX_UNDO_PREPARED) {
468
430
 
469
431
                                        fprintf(stderr,
470
 
                                                "InnoDB: Transaction %lu %lu"
 
432
                                                "InnoDB: Transaction "
 
433
                                                TRX_ID_FMT
471
434
                                                " was in the"
472
435
                                                " XA prepared state.\n",
473
 
                                                ut_dulint_get_high(trx->id),
474
 
                                                ut_dulint_get_low(trx->id));
 
436
                                                TRX_ID_PREP_PRINTF(trx->id));
475
437
 
476
438
                                        if (srv_force_recovery == 0) {
477
439
 
509
471
                        }
510
472
 
511
473
                        if (undo->dict_operation) {
512
 
                                trx->dict_operation = undo->dict_operation;
 
474
                                trx_set_dict_operation(
 
475
                                        trx, TRX_DICT_OP_TABLE);
513
476
                                trx->table_id = undo->table_id;
514
477
                        }
515
478
 
529
492
                        trx = trx_get_on_id(undo->trx_id);
530
493
 
531
494
                        if (NULL == trx) {
532
 
                                trx = trx_create(NULL);
 
495
                                trx = trx_create(trx_dummy_sess);
533
496
 
 
497
                                trx->is_recovered = TRUE;
534
498
                                trx->id = undo->trx_id;
535
499
                                trx->xid = undo->xid;
536
500
 
542
506
 
543
507
                                        if (undo->state == TRX_UNDO_PREPARED) {
544
508
                                                fprintf(stderr,
545
 
                                                        "InnoDB: Transaction"
546
 
                                                        " %lu %lu was in the"
 
509
                                                        "InnoDB: Transaction "
 
510
                                                        TRX_ID_FMT " was in the"
547
511
                                                        " XA prepared state.\n",
548
 
                                                        ut_dulint_get_high(
549
 
                                                                trx->id),
550
 
                                                        ut_dulint_get_low(
 
512
                                                        TRX_ID_PREP_PRINTF(
551
513
                                                                trx->id));
552
514
 
553
515
                                                if (srv_force_recovery == 0) {
588
550
                                trx_list_insert_ordered(trx);
589
551
 
590
552
                                if (undo->dict_operation) {
591
 
                                        trx->dict_operation
592
 
                                                = undo->dict_operation;
 
553
                                        trx_set_dict_operation(
 
554
                                                trx, TRX_DICT_OP_TABLE);
593
555
                                        trx->table_id = undo->table_id;
594
556
                                }
595
557
                        }
647
609
 
648
610
/********************************************************************
649
611
Starts a new transaction. */
650
 
 
 
612
UNIV_INTERN
651
613
ibool
652
614
trx_start_low(
653
615
/*==========*/
698
660
 
699
661
/********************************************************************
700
662
Starts a new transaction. */
701
 
 
 
663
UNIV_INTERN
702
664
ibool
703
665
trx_start(
704
666
/*======*/
721
683
 
722
684
/********************************************************************
723
685
Commits a transaction. */
724
 
 
 
686
UNIV_INTERN
725
687
void
726
688
trx_commit_off_kernel(
727
689
/*==================*/
728
690
        trx_t*  trx)    /* in: transaction */
729
691
{
730
692
        page_t*         update_hdr_page;
731
 
        dulint          lsn;
 
693
        ib_uint64_t     lsn             = 0;
732
694
        trx_rseg_t*     rseg;
733
695
        trx_undo_t*     undo;
734
 
        ibool           must_flush_log  = FALSE;
735
696
        mtr_t           mtr;
736
697
 
737
698
        ut_ad(mutex_own(&kernel_mutex));
746
707
 
747
708
                mtr_start(&mtr);
748
709
 
749
 
                must_flush_log = TRUE;
750
 
 
751
710
                /* Change the undo log segment states from TRX_UNDO_ACTIVE
752
711
                to some other state: these modifications to the file data
753
712
                structure define the transaction as committed in the file
795
754
                        trx_sys_update_mysql_binlog_offset(
796
755
                                trx->mysql_log_file_name,
797
756
                                trx->mysql_log_offset,
798
 
                                TRX_SYS_DRIZZLE_LOG_INFO, &mtr);
 
757
                                TRX_SYS_MYSQL_LOG_INFO, &mtr);
799
758
                        trx->mysql_log_file_name = NULL;
800
759
                }
801
760
 
856
815
 
857
816
        trx->read_view = NULL;
858
817
 
859
 
        if (must_flush_log) {
 
818
        if (lsn) {
860
819
 
861
820
                mutex_exit(&kernel_mutex);
862
821
 
933
892
        trx->rseg = NULL;
934
893
        trx->undo_no = ut_dulint_zero;
935
894
        trx->last_sql_stat_start.least_undo_no = ut_dulint_zero;
 
895
        trx->mysql_query_str = NULL;
936
896
 
937
897
        ut_ad(UT_LIST_GET_LEN(trx->wait_thrs) == 0);
938
898
        ut_ad(UT_LIST_GET_LEN(trx->trx_locks) == 0);
944
904
Cleans up a transaction at database startup. The cleanup is needed if
945
905
the transaction already got to the middle of a commit when the database
946
906
crashed, andf we cannot roll it back. */
947
 
 
 
907
UNIV_INTERN
948
908
void
949
909
trx_cleanup_at_db_startup(
950
910
/*======================*/
967
927
Assigns a read view for a consistent read query. All the consistent reads
968
928
within the same transaction will get the same read view, which is created
969
929
when this function is first called for a new started transaction. */
970
 
 
 
930
UNIV_INTERN
971
931
read_view_t*
972
932
trx_assign_read_view(
973
933
/*=================*/
1041
1001
The transaction must be in the TRX_QUE_LOCK_WAIT state. Puts it to
1042
1002
the TRX_QUE_RUNNING state and releases query threads which were
1043
1003
waiting for a lock in the wait_thrs list. */
1044
 
 
 
1004
UNIV_INTERN
1045
1005
void
1046
1006
trx_end_lock_wait(
1047
1007
/*==============*/
1199
1159
 
1200
1160
/********************************************************************
1201
1161
Sends a signal to a trx object. */
1202
 
 
 
1162
UNIV_INTERN
1203
1163
void
1204
1164
trx_sig_send(
1205
1165
/*=========*/
1286
1246
trx->graph_before_signal_handling != NULL, then returns control to the error
1287
1247
handling routine of the graph (currently just returns the control to the
1288
1248
graph root which then will send an error message to the client). */
1289
 
 
 
1249
UNIV_INTERN
1290
1250
void
1291
1251
trx_end_signal_handling(
1292
1252
/*====================*/
1307
1267
 
1308
1268
/********************************************************************
1309
1269
Starts handling of a trx signal. */
1310
 
 
 
1270
UNIV_INTERN
1311
1271
void
1312
1272
trx_sig_start_handle(
1313
1273
/*=================*/
1413
1373
/********************************************************************
1414
1374
Send the reply message when a signal in the queue of the trx has been
1415
1375
handled. */
1416
 
 
 
1376
UNIV_INTERN
1417
1377
void
1418
1378
trx_sig_reply(
1419
1379
/*==========*/
1447
1407
 
1448
1408
/********************************************************************
1449
1409
Removes a signal object from the trx signal queue. */
1450
 
 
 
1410
UNIV_INTERN
1451
1411
void
1452
1412
trx_sig_remove(
1453
1413
/*===========*/
1469
1429
 
1470
1430
/*************************************************************************
1471
1431
Creates a commit command node struct. */
1472
 
 
 
1432
UNIV_INTERN
1473
1433
commit_node_t*
1474
1434
commit_node_create(
1475
1435
/*===============*/
1487
1447
 
1488
1448
/***************************************************************
1489
1449
Performs an execution step for a commit type node in a query graph. */
1490
 
 
 
1450
UNIV_INTERN
1491
1451
que_thr_t*
1492
1452
trx_commit_step(
1493
1453
/*============*/
1535
1495
 
1536
1496
/**************************************************************************
1537
1497
Does the transaction commit for MySQL. */
1538
 
 
 
1498
UNIV_INTERN
1539
1499
ulint
1540
1500
trx_commit_for_mysql(
1541
1501
/*=================*/
1542
 
                        /* out: 0 or error number */
 
1502
                        /* out: DB_SUCCESS or error number */
1543
1503
        trx_t*  trx)    /* in: trx handle */
1544
1504
{
1545
1505
        /* Because we do not do the commit by sending an Innobase
1548
1508
 
1549
1509
        ut_a(trx);
1550
1510
 
 
1511
        trx_start_if_not_started(trx);
 
1512
 
1551
1513
        trx->op_info = "committing";
1552
1514
 
1553
 
        /* If we are doing the XA recovery of prepared transactions, then
1554
 
        the transaction object does not have an InnoDB session object, and we
1555
 
        set the dummy session that we use for all MySQL transactions. */
1556
 
 
1557
 
        if (trx->sess == NULL) {
1558
 
                /* Open a dummy session */
1559
 
 
1560
 
                if (!trx_dummy_sess) {
1561
 
                        mutex_enter(&kernel_mutex);
1562
 
 
1563
 
                        if (!trx_dummy_sess) {
1564
 
                                trx_dummy_sess = sess_open();
1565
 
                        }
1566
 
 
1567
 
                        mutex_exit(&kernel_mutex);
1568
 
                }
1569
 
 
1570
 
                trx->sess = trx_dummy_sess;
1571
 
        }
1572
 
 
1573
 
        trx_start_if_not_started(trx);
1574
 
 
1575
1515
        mutex_enter(&kernel_mutex);
1576
1516
 
1577
1517
        trx_commit_off_kernel(trx);
1580
1520
 
1581
1521
        trx->op_info = "";
1582
1522
 
1583
 
        return(0);
 
1523
        return(DB_SUCCESS);
1584
1524
}
1585
1525
 
1586
1526
/**************************************************************************
1587
1527
If required, flushes the log to disk if we called trx_commit_for_mysql()
1588
1528
with trx->flush_log_later == TRUE. */
1589
 
 
 
1529
UNIV_INTERN
1590
1530
ulint
1591
1531
trx_commit_complete_for_mysql(
1592
1532
/*==========================*/
1593
1533
                        /* out: 0 or error number */
1594
1534
        trx_t*  trx)    /* in: trx handle */
1595
1535
{
1596
 
        dulint  lsn     = trx->commit_lsn;
 
1536
        ib_uint64_t     lsn     = trx->commit_lsn;
1597
1537
 
1598
1538
        ut_a(trx);
1599
1539
 
1632
1572
 
1633
1573
/**************************************************************************
1634
1574
Marks the latest SQL statement ended. */
1635
 
 
 
1575
UNIV_INTERN
1636
1576
void
1637
1577
trx_mark_sql_stat_end(
1638
1578
/*==================*/
1652
1592
kernel mutex and must have called
1653
1593
innobase_mysql_prepare_print_arbitrary_session(), unless he knows that MySQL
1654
1594
or InnoDB cannot meanwhile change the info printed here. */
1655
 
 
 
1595
UNIV_INTERN
1656
1596
void
1657
1597
trx_print(
1658
1598
/*======*/
1663
1603
{
1664
1604
        ibool   newline;
1665
1605
 
1666
 
        fprintf(f, "TRANSACTION %lu %lu",
1667
 
                (ulong) ut_dulint_get_high(trx->id),
1668
 
                (ulong) ut_dulint_get_low(trx->id));
 
1606
        fprintf(f, "TRANSACTION " TRX_ID_FMT, TRX_ID_PREP_PRINTF(trx->id));
1669
1607
 
1670
1608
        switch (trx->conc_state) {
1671
1609
        case TRX_NOT_STARTED:
1697
1635
                fputs(trx->op_info, f);
1698
1636
        }
1699
1637
 
 
1638
        if (trx->is_recovered) {
 
1639
                fputs(" recovered trx", f);
 
1640
        }
 
1641
 
1700
1642
        if (trx->is_purge) {
1701
1643
                fputs(" purge trx", f);
1702
1644
        }
1745
1687
                fputs(", holds adaptive hash latch", f);
1746
1688
        }
1747
1689
 
1748
 
        if (ut_dulint_cmp(trx->undo_no, ut_dulint_zero) != 0) {
 
1690
        if (!ut_dulint_is_zero(trx->undo_no)) {
1749
1691
                newline = TRUE;
1750
1692
                fprintf(f, ", undo log entries %lu",
1751
1693
                        (ulong) ut_dulint_get_low(trx->undo_no));
1761
1703
}
1762
1704
 
1763
1705
/***********************************************************************
1764
 
Compares the "weight" (or size) of two transactions. The weight of one
1765
 
transaction is estimated as the number of altered rows + the number of
1766
 
locked rows. Transactions that have edited non-transactional tables are
1767
 
considered heavier than ones that have not. */
1768
 
 
 
1706
Compares the "weight" (or size) of two transactions. Transactions that
 
1707
have edited non-transactional tables are considered heavier than ones
 
1708
that have not. */
 
1709
UNIV_INTERN
1769
1710
int
1770
1711
trx_weight_cmp(
1771
1712
/*===========*/
1772
 
                        /* out: <0, 0 or >0; similar to strcmp(3) */
1773
 
        trx_t*  a,      /* in: the first transaction to be compared */
1774
 
        trx_t*  b)      /* in: the second transaction to be compared */
 
1713
                                /* out: <0, 0 or >0; similar to strcmp(3) */
 
1714
        const trx_t*    a,      /* in: the first transaction to be compared */
 
1715
        const trx_t*    b)      /* in: the second transaction to be compared */
1775
1716
{
1776
1717
        ibool   a_notrans_edit;
1777
1718
        ibool   b_notrans_edit;
1809
1750
                UT_LIST_GET_LEN(b->trx_locks));
1810
1751
#endif
1811
1752
 
1812
 
#define TRX_WEIGHT(t)   \
1813
 
        ut_dulint_add((t)->undo_no, UT_LIST_GET_LEN((t)->trx_locks))
1814
 
 
1815
1753
        return(ut_dulint_cmp(TRX_WEIGHT(a), TRX_WEIGHT(b)));
1816
1754
}
1817
1755
 
1818
1756
/********************************************************************
1819
1757
Prepares a transaction. */
1820
 
 
1821
 
static void
 
1758
UNIV_INLINE
 
1759
void
1822
1760
trx_prepare_off_kernel(
1823
1761
/*===================*/
1824
1762
        trx_t*  trx)    /* in: transaction */
1825
1763
{
1826
1764
        page_t*         update_hdr_page;
1827
1765
        trx_rseg_t*     rseg;
1828
 
        ibool           must_flush_log  = FALSE;
1829
 
        dulint          lsn;
 
1766
        ib_uint64_t     lsn             = 0;
1830
1767
        mtr_t           mtr;
1831
1768
 
1832
1769
        ut_ad(mutex_own(&kernel_mutex));
1839
1776
 
1840
1777
                mtr_start(&mtr);
1841
1778
 
1842
 
                must_flush_log = TRUE;
1843
 
 
1844
1779
                /* Change the undo log segment states from TRX_UNDO_ACTIVE
1845
1780
                to TRX_UNDO_PREPARED: these modifications to the file data
1846
1781
                structure define the transaction as prepared in the
1881
1816
        trx->conc_state = TRX_PREPARED;
1882
1817
        /*--------------------------------------*/
1883
1818
 
1884
 
        if (must_flush_log) {
 
1819
        if (lsn) {
1885
1820
                /* Depending on the my.cnf options, we may now write the log
1886
1821
                buffer to the log files, making the prepared state of the
1887
1822
                transaction durable if the OS does not crash. We may also
1930
1865
 
1931
1866
/**************************************************************************
1932
1867
Does the transaction prepare for MySQL. */
1933
 
 
 
1868
UNIV_INTERN
1934
1869
ulint
1935
1870
trx_prepare_for_mysql(
1936
1871
/*==================*/
1961
1896
/**************************************************************************
1962
1897
This function is used to find number of prepared transactions and
1963
1898
their transaction objects for a recovery. */
1964
 
 
 
1899
UNIV_INTERN
1965
1900
int
1966
1901
trx_recover_for_mysql(
1967
1902
/*==================*/
1996
1931
 
1997
1932
                        ut_print_timestamp(stderr);
1998
1933
                        fprintf(stderr,
1999
 
                                "  InnoDB: Transaction %lu %lu in"
 
1934
                                "  InnoDB: Transaction " TRX_ID_FMT " in"
2000
1935
                                " prepared state after recovery\n",
2001
 
                                (ulong) ut_dulint_get_high(trx->id),
2002
 
                                (ulong) ut_dulint_get_low(trx->id));
 
1936
                                TRX_ID_PREP_PRINTF(trx->id));
2003
1937
 
2004
1938
                        ut_print_timestamp(stderr);
2005
1939
                        fprintf(stderr,
2034
1968
/***********************************************************************
2035
1969
This function is used to find one X/Open XA distributed transaction
2036
1970
which is in the prepared state */
2037
 
 
 
1971
UNIV_INTERN
2038
1972
trx_t*
2039
1973
trx_get_trx_by_xid(
2040
1974
/*===============*/