~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2008-09-15 17:24:04 UTC
  • Revision ID: monty@inaugust.com-20080915172404-ygh6hiyu0q7qpa9x
Removed strndup calls.

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