diff options
author | Nirbhay Choubey <nirbhay@mariadb.com> | 2016-06-27 18:21:00 -0400 |
---|---|---|
committer | Nirbhay Choubey <nirbhay@mariadb.com> | 2016-06-27 18:21:00 -0400 |
commit | 90f222ea7dea4bebdb3ad93c4c1439e3ab08bbba (patch) | |
tree | 1d55a8e772d18d6857b8f81e5c354593c403a302 /sql/handler.cc | |
parent | ad3584bf728ad3ee48d99b81d8d14905524df4b8 (diff) | |
download | mariadb-git-90f222ea7dea4bebdb3ad93c4c1439e3ab08bbba.tar.gz |
MDEV-10235: Deadlock in CREATE TABLE .. AS SELECT .. if result set is empty in Galera
In CTAS, handlers get registered under statement transaction
(st_transactions::stmt), while ha_fake_trx_id(), used by CTAS,
looked under standard transaction (st_transactions::all) for
registered handlers, and thus it failed to grab a fake transaction
ID. As a result, with no valid transaction ID, wsrep commit failed
with an error.
ha_fake_trx_id() now looks for handlers registered under 'stmt'
in case 'all' is empty. Also modified the logic to print warning
only once if none of the registered handlers have fake_trx_id.
Diffstat (limited to 'sql/handler.cc')
-rw-r--r-- | sql/handler.cc | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/sql/handler.cc b/sql/handler.cc index 49e451e3836..147221abb97 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -6104,25 +6104,42 @@ int ha_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal) void ha_fake_trx_id(THD *thd) { DBUG_ENTER("ha_fake_trx_id"); + + bool no_fake_trx_id= true; + if (!WSREP(thd)) { DBUG_VOID_RETURN; } - THD_TRANS *trans= &thd->transaction.all; + /* Try statement transaction if standard one is not set. */ + THD_TRANS *trans= (thd->transaction.all.ha_list) ? &thd->transaction.all : + &thd->transaction.stmt; + Ha_trx_info *ha_info= trans->ha_list, *ha_info_next; for (; ha_info; ha_info= ha_info_next) { handlerton *hton= ha_info->ht(); - if (!hton->fake_trx_id) + if (hton->fake_trx_id) { - WSREP_WARN("cannot get fake InnoDB transaction ID"); - } - else hton->fake_trx_id(hton, thd); + + /* Got a fake trx id. */ + no_fake_trx_id= false; + + /* + We need transaction ID from just one storage engine providing + fake_trx_id (which will most likely be the case). + */ + break; + } ha_info_next= ha_info->next(); } + + if (unlikely(no_fake_trx_id)) + WSREP_WARN("Cannot get fake transaction ID from storage engine."); + DBUG_VOID_RETURN; } #endif /* WITH_WSREP */ |