summaryrefslogtreecommitdiff
path: root/innobase/trx/trx0undo.c
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/trx/trx0undo.c')
-rw-r--r--innobase/trx/trx0undo.c247
1 files changed, 212 insertions, 35 deletions
diff --git a/innobase/trx/trx0undo.c b/innobase/trx/trx0undo.c
index 8d1518753dd..88185973dfc 100644
--- a/innobase/trx/trx0undo.c
+++ b/innobase/trx/trx0undo.c
@@ -19,6 +19,7 @@ Created 3/26/1996 Heikki Tuuri
#include "srv0srv.h"
#include "trx0rec.h"
#include "trx0purge.h"
+#include "trx0xa.h"
/* How should the old versions in the history list be managed?
----------------------------------------------------------
@@ -97,10 +98,13 @@ trx_undo_mem_create(
TRX_UNDO_UPDATE */
dulint trx_id, /* in: id of the trx for which the undo log
is created */
+ XID* xid, /* in: X/Open XA transaction identification*/
ulint page_no,/* in: undo log header page number */
- ulint offset); /* in: undo log header byte offset on page */
+ ulint offset);/* in: undo log header byte offset on page */
/*******************************************************************
-Initializes a cached insert undo log header page for new use. */
+Initializes a cached insert undo log header page for new use. NOTE that this
+function has its own log record type MLOG_UNDO_HDR_REUSE. You must NOT change
+the operation of this function! */
static
ulint
trx_undo_insert_header_reuse(
@@ -181,7 +185,8 @@ trx_undo_get_prev_rec(
/* We have to go to the previous undo log page to look for the
previous record */
- return(trx_undo_get_prev_rec_from_prev_page(rec, page_no, offset, mtr));
+ return(trx_undo_get_prev_rec_from_prev_page(rec, page_no, offset,
+ mtr));
}
/***************************************************************************
@@ -473,15 +478,17 @@ trx_undo_header_create_log(
}
/*******************************************************************
-Creates a new undo log header in file. */
+Creates a new undo log header in file. NOTE that this function has its own
+log record type MLOG_UNDO_HDR_CREATE. You must NOT change the operation of
+this function! */
static
ulint
trx_undo_header_create(
/*===================*/
/* out: header byte offset on page */
page_t* undo_page, /* in: undo log segment header page,
- x-latched; it is assumed that there is
- TRX_UNDO_LOG_HDR_SIZE bytes free space
+ x-latched; it is assumed that there are
+ TRX_UNDO_LOG_XA_HDR_SIZE bytes free space
on it */
dulint trx_id, /* in: transaction id */
mtr_t* mtr) /* in: mtr */
@@ -503,9 +510,9 @@ trx_undo_header_create(
log_hdr = undo_page + free;
- new_free = free + TRX_UNDO_LOG_HDR_SIZE;
+ new_free = free + TRX_UNDO_LOG_OLD_HDR_SIZE;
- ut_ad(new_free <= UNIV_PAGE_SIZE);
+ ut_a(free + TRX_UNDO_LOG_XA_HDR_SIZE < UNIV_PAGE_SIZE - 100);
mach_write_to_2(page_hdr + TRX_UNDO_PAGE_START, new_free);
@@ -530,16 +537,102 @@ trx_undo_header_create(
mach_write_to_8(log_hdr + TRX_UNDO_TRX_ID, trx_id);
mach_write_to_2(log_hdr + TRX_UNDO_LOG_START, new_free);
- mach_write_to_2(log_hdr + TRX_UNDO_DICT_OPERATION, FALSE);
-
+ mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, FALSE);
+ mach_write_to_1(log_hdr + TRX_UNDO_DICT_TRANS, FALSE);
+
mach_write_to_2(log_hdr + TRX_UNDO_NEXT_LOG, 0);
mach_write_to_2(log_hdr + TRX_UNDO_PREV_LOG, prev_log);
-
+
+ /* Write the log record about the header creation */
trx_undo_header_create_log(undo_page, trx_id, mtr);
return(free);
}
+/************************************************************************
+Write X/Open XA Transaction Identification (XID) to undo log header */
+static
+void
+trx_undo_write_xid(
+/*===============*/
+ trx_ulogf_t* log_hdr,/* in: undo log header */
+ XID* xid, /* in: X/Open XA Transaction Identification */
+ mtr_t* mtr) /* in: mtr */
+{
+ mlog_write_ulint(log_hdr + TRX_UNDO_XA_FORMAT, xid->formatID,
+ MLOG_4BYTES, mtr);
+
+ mlog_write_ulint(log_hdr + TRX_UNDO_XA_TRID_LEN, xid->gtrid_length,
+ MLOG_4BYTES, mtr);
+
+ mlog_write_ulint(log_hdr + TRX_UNDO_XA_BQUAL_LEN, xid->bqual_length,
+ MLOG_4BYTES, mtr);
+
+ mlog_write_string(log_hdr + TRX_UNDO_XA_XID, xid->data,
+ XIDDATASIZE, mtr);
+}
+
+/************************************************************************
+Read X/Open XA Transaction Identification (XID) from undo log header */
+static
+void
+trx_undo_read_xid(
+/*==============*/
+ trx_ulogf_t* log_hdr,/* in: undo log header */
+ XID* xid) /* out: X/Open XA Transaction Identification */
+{
+ ulint i;
+
+ xid->formatID = mach_read_from_4(log_hdr + TRX_UNDO_XA_FORMAT);
+
+ xid->gtrid_length = mach_read_from_4(log_hdr + TRX_UNDO_XA_TRID_LEN);
+
+ xid->bqual_length = mach_read_from_4(log_hdr + TRX_UNDO_XA_BQUAL_LEN);
+
+ for (i = 0; i < XIDDATASIZE; i++) {
+ xid->data[i] = (char)mach_read_from_1(log_hdr +
+ TRX_UNDO_XA_XID + i);
+ }
+}
+
+/*******************************************************************
+Adds the XA XID after an undo log old-style header. */
+static
+void
+trx_undo_header_add_space_for_xid(
+/*==============================*/
+ page_t* undo_page,/* in: undo log segment header page */
+ trx_ulogf_t* log_hdr,/* in: undo log header */
+ mtr_t* mtr) /* in: mtr */
+{
+ trx_upagef_t* page_hdr;
+ ulint free;
+ ulint new_free;
+
+ page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
+
+ free = mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE);
+
+ /* free is now the end offset of the old style undo log header */
+
+ ut_a(free == (ulint)(log_hdr - undo_page) + TRX_UNDO_LOG_OLD_HDR_SIZE);
+
+ new_free = free + (TRX_UNDO_LOG_XA_HDR_SIZE
+ - TRX_UNDO_LOG_OLD_HDR_SIZE);
+
+ /* Add space for a XID after the header, update the free offset
+ fields on the undo log page and in the undo log header */
+
+ mlog_write_ulint(page_hdr + TRX_UNDO_PAGE_START, new_free,
+ MLOG_2BYTES, mtr);
+
+ mlog_write_ulint(page_hdr + TRX_UNDO_PAGE_FREE, new_free,
+ MLOG_2BYTES, mtr);
+
+ mlog_write_ulint(log_hdr + TRX_UNDO_LOG_START, new_free,
+ MLOG_2BYTES, mtr);
+}
+
/**************************************************************************
Writes the mtr log entry of an undo log header reuse. */
UNIV_INLINE
@@ -590,7 +683,9 @@ trx_undo_parse_page_header(
}
/*******************************************************************
-Initializes a cached insert undo log header page for new use. */
+Initializes a cached insert undo log header page for new use. NOTE that this
+function has its own log record type MLOG_UNDO_HDR_REUSE. You must NOT change
+the operation of this function! */
static
ulint
trx_undo_insert_header_reuse(
@@ -614,9 +709,11 @@ trx_undo_insert_header_reuse(
free = TRX_UNDO_SEG_HDR + TRX_UNDO_SEG_HDR_SIZE;
+ ut_a(free + TRX_UNDO_LOG_XA_HDR_SIZE < UNIV_PAGE_SIZE - 100);
+
log_hdr = undo_page + free;
- new_free = free + TRX_UNDO_LOG_HDR_SIZE;
+ new_free = free + TRX_UNDO_LOG_OLD_HDR_SIZE;
/* Insert undo data is not needed after commit: we may free all
the space on the page */
@@ -636,8 +733,10 @@ trx_undo_insert_header_reuse(
mach_write_to_8(log_hdr + TRX_UNDO_TRX_ID, trx_id);
mach_write_to_2(log_hdr + TRX_UNDO_LOG_START, new_free);
- mach_write_to_2(log_hdr + TRX_UNDO_DICT_OPERATION, FALSE);
+ mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, FALSE);
+ mach_write_to_1(log_hdr + TRX_UNDO_DICT_TRANS, FALSE);
+ /* Write the log record MLOG_UNDO_HDR_REUSE */
trx_undo_insert_header_reuse_log(undo_page, trx_id, mtr);
return(free);
@@ -800,7 +899,6 @@ trx_undo_free_page(
list */
ulint space, /* in: space */
ulint hdr_page_no, /* in: header page number */
- ulint hdr_offset, /* in: header offset */
ulint page_no, /* in: page number to free: must not be the
header page */
mtr_t* mtr) /* in: mtr which does not have a latch to any
@@ -813,7 +911,6 @@ trx_undo_free_page(
trx_rsegf_t* rseg_header;
ulint hist_size;
- UT_NOT_USED(hdr_offset);
ut_a(hdr_page_no != page_no);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
@@ -870,8 +967,7 @@ trx_undo_free_page_in_rollback(
#endif /* UNIV_SYNC_DEBUG */
last_page_no = trx_undo_free_page(undo->rseg, FALSE, undo->space,
- undo->hdr_page_no, undo->hdr_offset,
- page_no, mtr);
+ undo->hdr_page_no, page_no, mtr);
undo->last_page_no = last_page_no;
undo->size--;
@@ -1039,7 +1135,7 @@ loop:
trx_undo_empty_header_page(space, hdr_page_no, hdr_offset,
&mtr);
} else {
- trx_undo_free_page(rseg, TRUE, space, hdr_page_no, hdr_offset,
+ trx_undo_free_page(rseg, TRUE, space, hdr_page_no,
page_no, &mtr);
}
@@ -1123,7 +1219,9 @@ trx_undo_mem_create_at_db_start(
fil_addr_t last_addr;
page_t* last_page;
trx_undo_rec_t* rec;
-
+ XID xid;
+ ibool xid_exists = FALSE;
+
if (id >= TRX_RSEG_N_SLOTS) {
fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n", (ulong) id);
@@ -1145,15 +1243,30 @@ trx_undo_mem_create_at_db_start(
undo_header = undo_page + offset;
trx_id = mtr_read_dulint(undo_header + TRX_UNDO_TRX_ID, mtr);
+
+ xid_exists = mtr_read_ulint(undo_header + TRX_UNDO_XID_EXISTS,
+ MLOG_1BYTE, mtr);
+
+ /* Read X/Open XA transaction identification if it exists, or
+ set it to NULL. */
+
+ memset(&xid, 0, sizeof(xid));
+ xid.formatID = -1;
+
+ if (xid_exists == TRUE) {
+ trx_undo_read_xid(undo_header, &xid);
+ }
+
mutex_enter(&(rseg->mutex));
- undo = trx_undo_mem_create(rseg, id, type, trx_id, page_no, offset);
-
+ undo = trx_undo_mem_create(rseg, id, type, trx_id, &xid,
+ page_no, offset);
mutex_exit(&(rseg->mutex));
- undo->dict_operation = mtr_read_ulint(
- undo_header + TRX_UNDO_DICT_OPERATION,
- MLOG_2BYTES, mtr);
+ undo->dict_operation = mtr_read_ulint(
+ undo_header + TRX_UNDO_DICT_TRANS,
+ MLOG_1BYTE, mtr);
+
undo->table_id = mtr_read_dulint(undo_header + TRX_UNDO_TABLE_ID, mtr);
undo->state = state;
undo->size = flst_get_len(seg_header + TRX_UNDO_PAGE_LIST, mtr);
@@ -1272,7 +1385,8 @@ trx_undo_mem_create(
ulint type, /* in: type of the log: TRX_UNDO_INSERT or
TRX_UNDO_UPDATE */
dulint trx_id, /* in: id of the trx for which the undo log
- is created */
+ is created */
+ XID* xid, /* in: X/Open transaction identification */
ulint page_no,/* in: undo log header page number */
ulint offset) /* in: undo log header byte offset on page */
{
@@ -1295,6 +1409,7 @@ trx_undo_mem_create(
undo->state = TRX_UNDO_ACTIVE;
undo->del_marks = FALSE;
undo->trx_id = trx_id;
+ undo->xid = *xid;
undo->dict_operation = FALSE;
@@ -1322,6 +1437,7 @@ trx_undo_mem_init_for_reuse(
trx_undo_t* undo, /* in: undo log to init */
dulint trx_id, /* in: id of the trx for which the undo log
is created */
+ XID* xid, /* in: X/Open XA transaction identification*/
ulint offset) /* in: undo log header byte offset on page */
{
#ifdef UNIV_SYNC_DEBUG
@@ -1339,6 +1455,7 @@ trx_undo_mem_init_for_reuse(
undo->state = TRX_UNDO_ACTIVE;
undo->del_marks = FALSE;
undo->trx_id = trx_id;
+ undo->xid = *xid;
undo->dict_operation = FALSE;
@@ -1376,6 +1493,7 @@ trx_undo_create(
TRX_UNDO_UPDATE */
dulint trx_id, /* in: id of the trx for which the undo log
is created */
+ XID* xid, /* in: X/Open transaction identification*/
mtr_t* mtr) /* in: mtr */
{
trx_rsegf_t* rseg_header;
@@ -1410,10 +1528,12 @@ trx_undo_create(
page_no = buf_frame_get_page_no(undo_page);
- offset = trx_undo_header_create(undo_page, trx_id, mtr);
+ offset = trx_undo_header_create(undo_page, trx_id, mtr);
- undo = trx_undo_mem_create(rseg, id, type, trx_id, page_no, offset);
-
+ trx_undo_header_add_space_for_xid(undo_page, undo_page + offset, mtr);
+
+ undo = trx_undo_mem_create(rseg, id, type, trx_id, xid,
+ page_no, offset);
return(undo);
}
@@ -1432,6 +1552,7 @@ trx_undo_reuse_cached(
TRX_UNDO_UPDATE */
dulint trx_id, /* in: id of the trx for which the undo log
is used */
+ XID* xid, /* in: X/Open XA transaction identification */
mtr_t* mtr) /* in: mtr */
{
trx_undo_t* undo;
@@ -1476,15 +1597,19 @@ trx_undo_reuse_cached(
if (type == TRX_UNDO_INSERT) {
offset = trx_undo_insert_header_reuse(undo_page, trx_id, mtr);
+ trx_undo_header_add_space_for_xid(undo_page, undo_page + offset,
+ mtr);
} else {
ut_a(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
+ TRX_UNDO_PAGE_TYPE)
== TRX_UNDO_UPDATE);
offset = trx_undo_header_create(undo_page, trx_id, mtr);
+ trx_undo_header_add_space_for_xid(undo_page, undo_page + offset,
+ mtr);
}
- trx_undo_mem_init_for_reuse(undo, trx_id, offset);
+ trx_undo_mem_init_for_reuse(undo, trx_id, xid, offset);
return(undo);
}
@@ -1506,9 +1631,10 @@ trx_undo_mark_as_dict_operation(
hdr_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr);
- mlog_write_ulint(hdr_page + undo->hdr_offset + TRX_UNDO_DICT_OPERATION,
- trx->dict_operation, MLOG_2BYTES, mtr);
-
+ mlog_write_ulint(hdr_page + undo->hdr_offset +
+ TRX_UNDO_DICT_TRANS,
+ trx->dict_operation, MLOG_1BYTE, mtr);
+
mlog_write_dulint(hdr_page + undo->hdr_offset + TRX_UNDO_TABLE_ID,
trx->table_id, mtr);
@@ -1548,10 +1674,10 @@ trx_undo_assign_undo(
#endif /* UNIV_SYNC_DEBUG */
mutex_enter(&(rseg->mutex));
- undo = trx_undo_reuse_cached(rseg, type, trx->id, &mtr);
+ undo = trx_undo_reuse_cached(rseg, type, trx->id, &trx->xid, &mtr);
if (undo == NULL) {
- undo = trx_undo_create(rseg, type, trx->id, &mtr);
+ undo = trx_undo_create(rseg, type, trx->id, &trx->xid, &mtr);
if (undo == NULL) {
/* Did not succeed */
@@ -1632,6 +1758,57 @@ trx_undo_set_state_at_finish(
return(undo_page);
}
+/**********************************************************************
+Sets the state of the undo log segment at a transaction prepare. */
+
+page_t*
+trx_undo_set_state_at_prepare(
+/*==========================*/
+ /* out: undo log segment header page,
+ x-latched */
+ trx_t* trx, /* in: transaction */
+ trx_undo_t* undo, /* in: undo log memory copy */
+ mtr_t* mtr) /* in: mtr */
+{
+ trx_usegf_t* seg_hdr;
+ trx_upagef_t* page_hdr;
+ trx_ulogf_t* undo_header;
+ page_t* undo_page;
+ ulint offset;
+
+ ut_ad(trx && undo && mtr);
+
+ if (undo->id >= TRX_RSEG_N_SLOTS) {
+ fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
+ (ulong) undo->id);
+ mem_analyze_corruption((byte*)undo);
+ ut_error;
+ }
+
+ undo_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr);
+
+ seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
+ page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
+
+ /*------------------------------*/
+ undo->state = TRX_UNDO_PREPARED;
+ undo->xid = trx->xid;
+ /*------------------------------*/
+
+ mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, undo->state,
+ MLOG_2BYTES, mtr);
+
+ offset = mach_read_from_2(seg_hdr + TRX_UNDO_LAST_LOG);
+ undo_header = undo_page + offset;
+
+ mlog_write_ulint(undo_header + TRX_UNDO_XID_EXISTS,
+ TRUE, MLOG_1BYTE, mtr);
+
+ trx_undo_write_xid(undo_header, &undo->xid, mtr);
+
+ return(undo_page);
+}
+
/**************************************************************************
Adds the update undo log header as the first in the history list, and
frees the memory object, or puts it to the list of cached update undo log