Commit 90f222ea authored by Nirbhay Choubey's avatar Nirbhay Choubey

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.
parent ad3584bf
......@@ -68,4 +68,17 @@ CREATE TABLE `t2` (`c1` INT) ENGINE=INNODB SELECT * FROM t1;
COMMIT;
SET autocommit=1;
DROP TABLE t1, t2;
#
# MDEV-10235: Deadlock in CREATE TABLE ... AS SELECT .. if result set
# is empty in Galera
#
CREATE TABLE t1(c1 INT) ENGINE=INNODB;
INSERT INTO t1 VALUES(1);
CREATE TABLE t2 AS SELECT * FROM t1 WHERE c1=2;
SELECT * FROM t1;
c1
1
SELECT * FROM t2;
c1
DROP TABLE t1, t2;
# End of tests
......@@ -67,7 +67,6 @@ push @::global_suppressions,
qr|WSREP: gcs_caused\(\) returned .*|,
qr|WSREP: Protocol violation. JOIN message sender .* is not in state transfer \(SYNCED\). Message ignored.|,
qr(WSREP: Action message in non-primary configuration from member [0-9]*),
qr(WSREP: cannot get fake InnoDB transaction ID),
);
......
......@@ -68,6 +68,22 @@ SET autocommit=1;
# Cleanup
DROP TABLE t1, t2;
--echo #
--echo # MDEV-10235: Deadlock in CREATE TABLE ... AS SELECT .. if result set
--echo # is empty in Galera
--echo #
--connection node_1
CREATE TABLE t1(c1 INT) ENGINE=INNODB;
INSERT INTO t1 VALUES(1);
CREATE TABLE t2 AS SELECT * FROM t1 WHERE c1=2;
--connection node_2
SELECT * FROM t1;
SELECT * FROM t2;
# Cleanup
DROP TABLE t1, t2;
--source include/galera_end.inc
--echo # End of tests
call mtr.add_suppression("WSREP: MariaDB Galera does not support binlog format.*");
call mtr.add_suppression("WSREP: cannot get fake InnoDB transaction ID");
call mtr.add_suppression("WSREP: Cannot get fake transaction ID from storage engine.");
#
# MDEV-4227: Galera server should stop crashing on setting binlog_format STATEMENT
#
......
......@@ -2,7 +2,7 @@
--source include/have_binlog_format_row.inc
call mtr.add_suppression("WSREP: MariaDB Galera does not support binlog format.*");
call mtr.add_suppression("WSREP: cannot get fake InnoDB transaction ID");
call mtr.add_suppression("WSREP: Cannot get fake transaction ID from storage engine.");
--echo #
--echo # MDEV-4227: Galera server should stop crashing on setting binlog_format STATEMENT
......
......@@ -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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment