summaryrefslogtreecommitdiff
path: root/storage/innodb_plugin
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@oracle.com>2011-01-27 13:27:29 +0200
committerMarko Mäkelä <marko.makela@oracle.com>2011-01-27 13:27:29 +0200
commit786ac62c82038ed42278b3699b0661f0bb3c80ac (patch)
tree7d4761463c2434e3706e483cb89865398359e255 /storage/innodb_plugin
parente44703db76e87fccbcc2e51606f04b18b55a0544 (diff)
downloadmariadb-git-786ac62c82038ed42278b3699b0661f0bb3c80ac.tar.gz
Bug#59440 Race condition in XA ROLLBACK and XA COMMIT after server restart
trx_get_trx_by_xid(): Invalidate trx->xid after a successful lookup, so that subsequent callers will not find the same transaction. The only callers of trx_get_trx_by_xid() will be invoking innobase_commit_low() or innobase_rollback_trx(), and those code paths should not depend on trx->xid. rb://584 approved by Jimmy Yang
Diffstat (limited to 'storage/innodb_plugin')
-rw-r--r--storage/innodb_plugin/ChangeLog6
-rw-r--r--storage/innodb_plugin/include/trx0trx.h4
-rw-r--r--storage/innodb_plugin/trx/trx0trx.c25
3 files changed, 19 insertions, 16 deletions
diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog
index e2fdeecfcc1..3e14b0052e7 100644
--- a/storage/innodb_plugin/ChangeLog
+++ b/storage/innodb_plugin/ChangeLog
@@ -1,3 +1,9 @@
+2011-01-27 The InnoDB Team
+
+ * include/trx0trx.h, trx/trx0trx.c:
+ Bug#59440 Race condition in XA ROLLBACK and XA COMMIT
+ after server restart
+
2011-01-25 The InnoDB Team
* row/row0upd.c:
diff --git a/storage/innodb_plugin/include/trx0trx.h b/storage/innodb_plugin/include/trx0trx.h
index abd175d365b..833bae4a4ff 100644
--- a/storage/innodb_plugin/include/trx0trx.h
+++ b/storage/innodb_plugin/include/trx0trx.h
@@ -214,12 +214,12 @@ trx_recover_for_mysql(
/*******************************************************************//**
This function is used to find one X/Open XA distributed transaction
which is in the prepared state
-@return trx or NULL */
+@return trx or NULL; on match, the trx->xid will be invalidated */
UNIV_INTERN
trx_t *
trx_get_trx_by_xid(
/*===============*/
- XID* xid); /*!< in: X/Open XA transaction identification */
+ const XID* xid); /*!< in: X/Open XA transaction identifier */
/**********************************************************************//**
If required, flushes the log to disk if we called trx_commit_for_mysql()
with trx->flush_log_later == TRUE.
diff --git a/storage/innodb_plugin/trx/trx0trx.c b/storage/innodb_plugin/trx/trx0trx.c
index ee744fd58b1..f0bbf220815 100644
--- a/storage/innodb_plugin/trx/trx0trx.c
+++ b/storage/innodb_plugin/trx/trx0trx.c
@@ -2010,18 +2010,18 @@ trx_recover_for_mysql(
/*******************************************************************//**
This function is used to find one X/Open XA distributed transaction
which is in the prepared state
-@return trx or NULL */
+@return trx or NULL; on match, the trx->xid will be invalidated */
UNIV_INTERN
trx_t*
trx_get_trx_by_xid(
/*===============*/
- XID* xid) /*!< in: X/Open XA transaction identification */
+ const XID* xid) /*!< in: X/Open XA transaction identifier */
{
trx_t* trx;
if (xid == NULL) {
- return (NULL);
+ return(NULL);
}
mutex_enter(&kernel_mutex);
@@ -2034,10 +2034,16 @@ trx_get_trx_by_xid(
of gtrid_lenght+bqual_length bytes should be
the same */
- if (xid->gtrid_length == trx->xid.gtrid_length
+ if (trx->conc_state == TRX_PREPARED
+ && xid->gtrid_length == trx->xid.gtrid_length
&& xid->bqual_length == trx->xid.bqual_length
&& memcmp(xid->data, trx->xid.data,
xid->gtrid_length + xid->bqual_length) == 0) {
+
+ /* Invalidate the XID, so that subsequent calls
+ will not find it. */
+ memset(&trx->xid, 0, sizeof(trx->xid));
+ trx->xid.formatID = -1;
break;
}
@@ -2046,14 +2052,5 @@ trx_get_trx_by_xid(
mutex_exit(&kernel_mutex);
- if (trx) {
- if (trx->conc_state != TRX_PREPARED) {
-
- return(NULL);
- }
-
- return(trx);
- } else {
- return(NULL);
- }
+ return(trx);
}