From 81c88ab7cd824779d4869581b5a6b51f6cc305d4 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 16 Oct 2023 17:37:16 +0200 Subject: [PATCH] MDEV-28820 MyISAM wrong server status flags MyISAM tables no longer take transactional metadata locks unless there already is an active transaction. --- mysql-test/main/mdl.result | 44 +++++++++++++++++++++++++++ mysql-test/main/mdl.test | 43 ++++++++++++++++++++++++++ mysql-test/main/myisam_recover.result | 3 +- mysql-test/main/myisam_recover.test | 3 +- mysql-test/main/schema.result | 4 +-- mysql-test/main/schema.test | 4 +-- mysql-test/main/sp-lock.result | 4 +-- mysql-test/main/sp-lock.test | 4 +-- sql/sql_parse.cc | 2 +- 9 files changed, 98 insertions(+), 13 deletions(-) diff --git a/mysql-test/main/mdl.result b/mysql-test/main/mdl.result index 883f35674c0..c6fa2c2dbde 100644 --- a/mysql-test/main/mdl.result +++ b/mysql-test/main/mdl.result @@ -88,3 +88,47 @@ unlock tables; connection default; disconnect locker; DROP TABLE t1,t3; +# +# MDEV-28820 MyISAM wrong server status flags +# +create table t1 (a int); +set autocommit=0; +select @@in_transaction; +@@in_transaction +0 +select * from t1; +a +select @@in_transaction; +@@in_transaction +0 +connect foo,localhost,root; +drop table t1; +connection default; +set autocommit=1; +create table t1 (a int); +create table t2 (b int) engine=innodb; +set autocommit=0; +select @@in_transaction; +@@in_transaction +0 +select * from t2; +b +select @@in_transaction; +@@in_transaction +1 +select * from t1; +a +connection foo; +drop table t1; +connection default; +select * from t1; +a +commit; +connection foo; +disconnect foo; +connection default; +set autocommit=default; +drop table t2; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/mdl.test b/mysql-test/main/mdl.test index 54e23801231..b0ce408ec13 100644 --- a/mysql-test/main/mdl.test +++ b/mysql-test/main/mdl.test @@ -80,3 +80,46 @@ connection default; disconnect locker; DROP TABLE t1,t3; --enable_service_connection + +--echo # +--echo # MDEV-28820 MyISAM wrong server status flags +--echo # +# MyISAM alone doesn't start a transaction or takes transactional MDL +create table t1 (a int); +set autocommit=0; +select @@in_transaction; +select * from t1; +select @@in_transaction; +connect foo,localhost,root; +drop table t1; +connection default; +set autocommit=1; + +# MyISAM in a transaction (started by InnoDB) takes transactional MDL all right +create table t1 (a int); +create table t2 (b int) engine=innodb; +set autocommit=0; +select @@in_transaction; +select * from t2; +select @@in_transaction; +select * from t1; +connection foo; +send drop table t1; +connection default; +let $wait_condition= + select count(*) > 0 from information_schema.processlist + where state = "Waiting for table metadata lock"; +--source include/wait_condition.inc +select * from t1; +commit; + +connection foo; +reap; +disconnect foo; +connection default; +set autocommit=default; +drop table t2; + +--echo # +--echo # End of 10.4 tests +--echo # diff --git a/mysql-test/main/myisam_recover.result b/mysql-test/main/myisam_recover.result index a619f2cdd4a..f42919bf186 100644 --- a/mysql-test/main/myisam_recover.result +++ b/mysql-test/main/myisam_recover.result @@ -126,7 +126,7 @@ test.t1 check error Record-count is not ok; is 2 Should be: 1 test.t1 check warning Found 2 key parts. Should be: 1 test.t1 check error Corrupt # At this point we have a corrupt t1 -set autocommit = 0; +start transaction; select * from t2; a 1 @@ -145,7 +145,6 @@ ALTER TABLE t2 ADD val INT; connection default; # With fix we should have alter table waiting for t2 lock here. ROLLBACK; -SET autocommit = 1; connection con2; connection default; disconnect con2; diff --git a/mysql-test/main/myisam_recover.test b/mysql-test/main/myisam_recover.test index f78fc38a675..00f99265464 100644 --- a/mysql-test/main/myisam_recover.test +++ b/mysql-test/main/myisam_recover.test @@ -135,7 +135,7 @@ flush table t1; check table t1; --echo # At this point we have a corrupt t1 -set autocommit = 0; +start transaction; select * from t2; --echo # Without fix select from t1 will break the transaction. After the fix --echo # transaction should be active and should hold lock on table t2. Alter @@ -153,7 +153,6 @@ let $wait_condition= LIKE "Waiting%" AND info = "ALTER TABLE t2 ADD val INT"; --source include/wait_condition.inc ROLLBACK; -SET autocommit = 1; connection con2; --reap diff --git a/mysql-test/main/schema.result b/mysql-test/main/schema.result index bdb25a98250..6fa0dbb3a96 100644 --- a/mysql-test/main/schema.result +++ b/mysql-test/main/schema.result @@ -18,14 +18,14 @@ connect con2, localhost, root; connection default; CREATE SCHEMA schema1; CREATE TABLE schema1.t1 (a INT); -SET autocommit= FALSE; +START TRANSACTION; INSERT INTO schema1.t1 VALUES (1); connection con2; DROP SCHEMA schema1; connection default; ALTER SCHEMA schema1 DEFAULT CHARACTER SET utf8; Got one of the listed errors -SET autocommit= TRUE; +COMMIT; connection con2; connection default; disconnect con2; diff --git a/mysql-test/main/schema.test b/mysql-test/main/schema.test index 474c9c7e9c7..b984ebb8639 100644 --- a/mysql-test/main/schema.test +++ b/mysql-test/main/schema.test @@ -25,7 +25,7 @@ connection default; CREATE SCHEMA schema1; CREATE TABLE schema1.t1 (a INT); -SET autocommit= FALSE; +START TRANSACTION; INSERT INTO schema1.t1 VALUES (1); connection con2; @@ -40,7 +40,7 @@ let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist # Listing the error twice to prevent result diffences based on filename. --error 1,1 ALTER SCHEMA schema1 DEFAULT CHARACTER SET utf8; -SET autocommit= TRUE; +COMMIT; connection con2; --reap diff --git a/mysql-test/main/sp-lock.result b/mysql-test/main/sp-lock.result index 4d9cbc8ad51..e7ebc3aecb8 100644 --- a/mysql-test/main/sp-lock.result +++ b/mysql-test/main/sp-lock.result @@ -463,8 +463,8 @@ drop function f1; create function f1() returns varchar(20) return "f1()"; create function f2() returns varchar(20) return "f2()"; create view v1 as select f1() as a; -set @@session.autocommit=0; lock table v1 read; +start transaction; select * from v1; a f1() @@ -486,6 +486,7 @@ connection con2; # Reaping 'drop function f2'... connection default; unlock tables; +commit; connection con1; # Reaping 'drop function f1'... connection default; @@ -494,7 +495,6 @@ ERROR 42000: FUNCTION test.f1 does not exist drop function f2; ERROR 42000: FUNCTION test.f2 does not exist drop view v1; -set @@session.autocommit=default; # # 8) Check the situation when we're preparing or executing a # prepared statement, and as part of that try to flush the diff --git a/mysql-test/main/sp-lock.test b/mysql-test/main/sp-lock.test index 224169a68b5..9ca071070ac 100644 --- a/mysql-test/main/sp-lock.test +++ b/mysql-test/main/sp-lock.test @@ -537,8 +537,8 @@ drop function f1; create function f1() returns varchar(20) return "f1()"; create function f2() returns varchar(20) return "f2()"; create view v1 as select f1() as a; -set @@session.autocommit=0; lock table v1 read; +start transaction; select * from v1; savepoint sv; select f2(); @@ -565,6 +565,7 @@ connection con2; reap; connection default; unlock tables; +commit; connection con1; --echo # Reaping 'drop function f1'... reap; @@ -574,7 +575,6 @@ drop function f1; --error ER_SP_DOES_NOT_EXIST drop function f2; drop view v1; -set @@session.autocommit=default; --echo # --echo # 8) Check the situation when we're preparing or executing a diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f5a80e9e5e5..c13637a3cfd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6319,7 +6319,7 @@ finish: thd->release_transactional_locks(); } } - else if (! thd->in_sub_stmt && ! thd->in_multi_stmt_transaction_mode()) + else if (! thd->in_sub_stmt && ! thd->in_active_multi_stmt_transaction()) { /* - If inside a multi-statement transaction,