From f0b494b31e008a25f08df8dcd64d428c749fae08 Mon Sep 17 00:00:00 2001 From: Satya Bodapati Date: Tue, 10 Sep 2024 16:33:52 +0100 Subject: [PATCH] PS-9306: MySQL 8.0.38, 8.4.1 and 9.0.0 crashes on restart if database has 10K tables or more Upstream fixed the problem in 8.0.39 release but no testcase is attached to the bug fix. This commit introduces a mtr testcase. It creates 8192 tables, restarts the server and it should come up --- .../innodb/r/percona_create_table_8k.result | 50 +++++++++++ .../innodb/t/percona_create_table_8k.test | 88 +++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 mysql-test/suite/innodb/r/percona_create_table_8k.result create mode 100644 mysql-test/suite/innodb/t/percona_create_table_8k.test diff --git a/mysql-test/suite/innodb/r/percona_create_table_8k.result b/mysql-test/suite/innodb/r/percona_create_table_8k.result new file mode 100644 index 000000000000..161ef4fe36c8 --- /dev/null +++ b/mysql-test/suite/innodb/r/percona_create_table_8k.result @@ -0,0 +1,50 @@ +# +# PS-9306 : MySQL 8.0.38, 8.4.1 and 9.0.0 crashes on restart if database has 10K tables or more +# +CREATE DATABASE test_8k; +CREATE PROCEDURE create_tables(start_index INT, end_index INT) +BEGIN +DECLARE i INT; +SET i = start_index; +WHILE i < end_index DO +SET @table_name = CONCAT('table_', i); +SET @create_stmt = CONCAT('CREATE TABLE IF NOT EXISTS test_8k.', @table_name, ' (id INT PRIMARY KEY AUTO_INCREMENT, data VARCHAR(255));'); +PREPARE stmt FROM @create_stmt; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; +SET i = i + 1; +END WHILE; +END| +CALL create_tables(0*1024,(0+1)*1024); +CALL create_tables(1*1024,(1+1)*1024); +CALL create_tables(2*1024,(2+1)*1024); +CALL create_tables(3*1024,(3+1)*1024); +CALL create_tables(4*1024,(4+1)*1024); +CALL create_tables(5*1024,(5+1)*1024); +CALL create_tables(6*1024,(6+1)*1024); +CALL create_tables(7*1024,(7+1)*1024); +# restart +CREATE PROCEDURE drop_tables(start_index INT, end_index INT) +BEGIN +DECLARE i INT; +SET i = start_index; +WHILE i < end_index DO +SET @table_name = CONCAT('table_', i); +SET @create_stmt = CONCAT('DROP TABLE test_8k.', @table_name, ';'); +PREPARE stmt FROM @create_stmt; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; +SET i = i + 1; +END WHILE; +END| +CALL drop_tables(0*1024,(0+1)*1024); +CALL drop_tables(1*1024,(1+1)*1024); +CALL drop_tables(2*1024,(2+1)*1024); +CALL drop_tables(3*1024,(3+1)*1024); +CALL drop_tables(4*1024,(4+1)*1024); +CALL drop_tables(5*1024,(5+1)*1024); +CALL drop_tables(6*1024,(6+1)*1024); +CALL drop_tables(7*1024,(7+1)*1024); +DROP DATABASE test_8k; +DROP PROCEDURE create_tables; +DROP PROCEDURE drop_tables; diff --git a/mysql-test/suite/innodb/t/percona_create_table_8k.test b/mysql-test/suite/innodb/t/percona_create_table_8k.test new file mode 100644 index 000000000000..1fe31315c714 --- /dev/null +++ b/mysql-test/suite/innodb/t/percona_create_table_8k.test @@ -0,0 +1,88 @@ +--echo # +--echo # PS-9306 : MySQL 8.0.38, 8.4.1 and 9.0.0 crashes on restart if database has 10K tables or more +--echo # + +CREATE DATABASE test_8k; +--source include/count_sessions.inc + +DELIMITER |; +CREATE PROCEDURE create_tables(start_index INT, end_index INT) +BEGIN + DECLARE i INT; + SET i = start_index; + WHILE i < end_index DO + SET @table_name = CONCAT('table_', i); + SET @create_stmt = CONCAT('CREATE TABLE IF NOT EXISTS test_8k.', @table_name, ' (id INT PRIMARY KEY AUTO_INCREMENT, data VARCHAR(255));'); + PREPARE stmt FROM @create_stmt; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; + SET i = i + 1; + END WHILE; +END| +DELIMITER ;| + +let $connections=8; +let $i=0; +while ($i < $connections) { + --connect(C$i,localhost,root,,test) + --send_eval CALL create_tables($i*1024,($i+1)*1024) + inc $i; +} + +let $i=0; +while ($i < $connections) { + --connection C$i + reap; + --disconnect C$i + --source include/wait_until_disconnected.inc + inc $i; +} +--connection default +--source include/wait_until_count_sessions.inc + +--source include/restart_mysqld.inc + +--assert(`SELECT COUNT(*)=8192 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test_8k'`) + +--source include/count_sessions.inc + +DELIMITER |; +CREATE PROCEDURE drop_tables(start_index INT, end_index INT) +BEGIN + DECLARE i INT; + SET i = start_index; + WHILE i < end_index DO + SET @table_name = CONCAT('table_', i); + SET @create_stmt = CONCAT('DROP TABLE test_8k.', @table_name, ';'); + PREPARE stmt FROM @create_stmt; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; + SET i = i + 1; + END WHILE; +END| +DELIMITER ;| + +let $connections=8; +let $i=0; +while ($i < $connections) { + --connect(C$i,localhost,root,,test) + --send_eval CALL drop_tables($i*1024,($i+1)*1024) + inc $i; +} + +let $i=0; +while ($i < $connections) { + --connection C$i + reap; + --disconnect C$i + --source include/wait_until_disconnected.inc + inc $i; +} +--connection default +--source include/wait_until_count_sessions.inc + +--assert(`SELECT COUNT(*)=0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test_8k'`) + +DROP DATABASE test_8k; +DROP PROCEDURE create_tables; +DROP PROCEDURE drop_tables;