From: Dmitry Shulga Date: December 6 2012 10:10am Subject: bzr push into mysql-5.6 branch (Dmitry.Shulga:4737 to 4738) Bug#14729757 List-Archive: http://lists.mysql.com/commits/145448 X-Bug: 14729757 Message-Id: <20121206101045.70226.63314.4738@dhcp-uk-twvpn-2-vpnpool-10-175-32-131.vpn.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 4738 Dmitry Shulga 2012-12-06 [merge] Auto-merge of patch for bug#14729757 from mysql-5.5 modified: sql/sql_class.cc sql/transaction.cc 4737 Alexander Barkov 2012-12-06 Minor refactoring in GIS code: incapsulating "thread_start": moving it into the private section and adding public methods to access. Helps to debug easier, e.g. set breakpoints when "thread_start" is set or read. modified: sql/gcalc_tools.cc sql/gcalc_tools.h === modified file 'sql/sql_class.cc' --- a/sql/sql_class.cc 2012-11-27 15:39:15 +0000 +++ b/sql/sql_class.cc 2012-12-06 10:04:50 +0000 @@ -4673,9 +4673,14 @@ bool xid_cache_insert(XID *xid, enum xa_ bool xid_cache_insert(XID_STATE *xid_state) { mysql_mutex_lock(&LOCK_xid_cache); - DBUG_ASSERT(my_hash_search(&xid_cache, xid_state->xid.key(), - xid_state->xid.key_length())==0); - my_bool res=my_hash_insert(&xid_cache, (uchar*)xid_state); + if (my_hash_search(&xid_cache, xid_state->xid.key(), + xid_state->xid.key_length())) + { + mysql_mutex_unlock(&LOCK_xid_cache); + my_error(ER_XAER_DUPID, MYF(0)); + return true; + } + bool res= my_hash_insert(&xid_cache, (uchar*)xid_state); mysql_mutex_unlock(&LOCK_xid_cache); return res; } === modified file 'sql/transaction.cc' --- a/sql/transaction.cc 2012-08-21 06:10:46 +0000 +++ b/sql/transaction.cc 2012-12-06 10:04:50 +0000 @@ -665,15 +665,19 @@ bool trans_xa_start(THD *thd) my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]); else if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction()) my_error(ER_XAER_OUTSIDE, MYF(0)); - else if (xid_cache_search(thd->lex->xid)) - my_error(ER_XAER_DUPID, MYF(0)); else if (!trans_begin(thd)) { DBUG_ASSERT(thd->transaction.xid_state.xid.is_null()); thd->transaction.xid_state.xa_state= XA_ACTIVE; thd->transaction.xid_state.rm_error= 0; thd->transaction.xid_state.xid.set(thd->lex->xid); - xid_cache_insert(&thd->transaction.xid_state); + if (xid_cache_insert(&thd->transaction.xid_state)) + { + thd->transaction.xid_state.xa_state= XA_NOTR; + thd->transaction.xid_state.xid.null(); + trans_rollback(thd); + DBUG_RETURN(true); + } DBUG_RETURN(FALSE); } @@ -759,6 +763,16 @@ bool trans_xa_commit(THD *thd) if (!thd->transaction.xid_state.xid.eq(thd->lex->xid)) { + /* + xid_state.in_thd is always true beside of xa recovery procedure. + Note, that there is no race condition here between xid_cache_search + and xid_cache_delete, since we always delete our own XID + (thd->lex->xid == thd->transaction.xid_state.xid). + The only case when thd->lex->xid != thd->transaction.xid_state.xid + and xid_state->in_thd == 0 is in the function + 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); res= !xs || xs->in_thd; if (res) No bundle (reason: useless for push emails).