summaryrefslogtreecommitdiff
path: root/sql/transaction.cc
diff options
context:
space:
mode:
authorSergey Vojtovich <svoj@mariadb.org>2015-03-16 18:44:06 +0400
committerSergey Vojtovich <svoj@mariadb.org>2015-03-16 19:07:51 +0400
commit6bd24deab46efc7d67401ac1b30194f03a03ad02 (patch)
treeb6d6667d8b12429b0ffc96a850a88df1c8a2304b /sql/transaction.cc
parent18e9c314e43271debf58f3c3e5bf454eab655799 (diff)
downloadmariadb-git-6bd24deab46efc7d67401ac1b30194f03a03ad02.tar.gz
MDEV-7728 - Improve xid cache scalability by using lock-free hash
XID cache is now based on lock-free hash. Also fixed lf_hash_destroy() to call alloc destructor. Note that previous implementation had race condition when thread was accessing XA owned by different thread. This new implementation doesn't fix it either.
Diffstat (limited to 'sql/transaction.cc')
-rw-r--r--sql/transaction.cc27
1 files changed, 19 insertions, 8 deletions
diff --git a/sql/transaction.cc b/sql/transaction.cc
index 22e3ad7f87c..d6ef160206b 100644
--- a/sql/transaction.cc
+++ b/sql/transaction.cc
@@ -738,7 +738,7 @@ bool trans_xa_start(THD *thd)
thd->transaction.xid_state.xa_state= XA_ACTIVE;
thd->transaction.xid_state.rm_error= 0;
thd->transaction.xid_state.xid.set(thd->lex->xid);
- if (xid_cache_insert(&thd->transaction.xid_state))
+ if (xid_cache_insert(thd, &thd->transaction.xid_state))
{
thd->transaction.xid_state.xa_state= XA_NOTR;
thd->transaction.xid_state.xid.null();
@@ -801,7 +801,7 @@ bool trans_xa_prepare(THD *thd)
my_error(ER_XAER_NOTA, MYF(0));
else if (ha_prepare(thd))
{
- xid_cache_delete(&thd->transaction.xid_state);
+ xid_cache_delete(thd, &thd->transaction.xid_state);
thd->transaction.xid_state.xa_state= XA_NOTR;
my_error(ER_XA_RBROLLBACK, MYF(0));
}
@@ -830,6 +830,11 @@ bool trans_xa_commit(THD *thd)
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
+ if (thd->fix_xid_hash_pins())
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
/*
xid_state.in_thd is always true beside of xa recovery procedure.
Note, that there is no race condition here between xid_cache_search
@@ -840,7 +845,7 @@ bool trans_xa_commit(THD *thd)
xa_cache_insert(XID, xa_states), which is called before starting
client connections, and thus is always single-threaded.
*/
- XID_STATE *xs= xid_cache_search(thd->lex->xid);
+ XID_STATE *xs= xid_cache_search(thd, thd->lex->xid);
res= !xs || xs->in_thd;
if (res)
my_error(ER_XAER_NOTA, MYF(0));
@@ -848,7 +853,7 @@ bool trans_xa_commit(THD *thd)
{
res= xa_trans_rolled_back(xs);
ha_commit_or_rollback_by_xid(thd->lex->xid, !res);
- xid_cache_delete(xs);
+ xid_cache_delete(thd, xs);
}
DBUG_RETURN(res);
}
@@ -911,7 +916,7 @@ bool trans_xa_commit(THD *thd)
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
- xid_cache_delete(&thd->transaction.xid_state);
+ xid_cache_delete(thd, &thd->transaction.xid_state);
thd->transaction.xid_state.xa_state= XA_NOTR;
DBUG_RETURN(res);
@@ -935,14 +940,20 @@ bool trans_xa_rollback(THD *thd)
if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
- XID_STATE *xs= xid_cache_search(thd->lex->xid);
+ if (thd->fix_xid_hash_pins())
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+
+ XID_STATE *xs= xid_cache_search(thd, thd->lex->xid);
if (!xs || xs->in_thd)
my_error(ER_XAER_NOTA, MYF(0));
else
{
xa_trans_rolled_back(xs);
ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
- xid_cache_delete(xs);
+ xid_cache_delete(thd, xs);
}
DBUG_RETURN(thd->get_stmt_da()->is_error());
}
@@ -961,7 +972,7 @@ bool trans_xa_rollback(THD *thd)
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
- xid_cache_delete(&thd->transaction.xid_state);
+ xid_cache_delete(thd, &thd->transaction.xid_state);
thd->transaction.xid_state.xa_state= XA_NOTR;
DBUG_RETURN(res);