From 72c728febaed52c98d8649a4e3259935f89452b4 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 15 Nov 2022 11:34:00 +0400 Subject: [PATCH 1/4] MDEV-29370 Functions in packages are slow and seems to ignore deterministic --- .../suite/compat/oracle/r/sp-package.result | 75 +++++++++++++++++++ .../suite/compat/oracle/t/sp-package.test | 72 ++++++++++++++++++ sql/sql_yacc.yy | 2 + 3 files changed, 149 insertions(+) diff --git a/mysql-test/suite/compat/oracle/r/sp-package.result b/mysql-test/suite/compat/oracle/r/sp-package.result index 6fbe568f719..096527342d0 100644 --- a/mysql-test/suite/compat/oracle/r/sp-package.result +++ b/mysql-test/suite/compat/oracle/r/sp-package.result @@ -3270,3 +3270,78 @@ a This is db1.pkg1.p1 DROP DATABASE db1; DROP DATABASE db2; +# +# MDEV-29370 Functions in packages are slow and seems to ignore deterministic +# +SET SQL_MODE=ORACLE; +CREATE TABLE t1 (c1 CHAR(1)); +CREATE FUNCTION f1_deterministic() +RETURN CHAR(1) +DETERMINISTIC +IS +BEGIN +RETURN 'X'; +END; +// +CREATE FUNCTION f2_not_deterministic() +RETURN CHAR(1) +IS +BEGIN +RETURN 'X'; +END; +// +CREATE PACKAGE pkg1 +IS +PROCEDURE t1_populate(numrows INTEGER); +FUNCTION f3_deterministic() RETURN CHAR(1) DETERMINISTIC; +FUNCTION f4_not_deterministic() RETURN CHAR(1); +END; +// +CREATE PACKAGE BODY pkg1 +IS +PROCEDURE t1_populate(numrounds INTEGER) +IS +i INTEGER; +BEGIN +INSERT INTO t1 VALUES('Y'); +FOR i IN 1..numrounds LOOP +INSERT INTO t1 SELECT * FROM t1; +END LOOP; +END; +FUNCTION f3_deterministic() RETURN CHAR(1) DETERMINISTIC COMMENT 'xxx' + IS +BEGIN +RETURN 'X'; +END; +FUNCTION f4_not_deterministic() RETURN CHAR(1) +IS +BEGIN +RETURN 'X'; +END; +END; +// +CALL pkg1.t1_populate(3); +EXPLAIN EXTENDED SELECT 'Deterministic function', COUNT(*) FROM t1 WHERE c1 = f1_deterministic(); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where +Warnings: +Note 1003 select 'Deterministic function' AS "Deterministic function",count(0) AS "COUNT(*)" from "test"."t1" where "test"."t1"."c1" = ("f1_deterministic"()) +EXPLAIN EXTENDED SELECT 'Non-deterministic function', COUNT(*) FROM t1 WHERE c1 = f2_not_deterministic(); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where +Warnings: +Note 1003 select 'Non-deterministic function' AS "Non-deterministic function",count(0) AS "COUNT(*)" from "test"."t1" where "test"."t1"."c1" = "f2_not_deterministic"() +EXPLAIN EXTENDED SELECT 'Deterministic package function', COUNT(*) FROM t1 WHERE c1 = pkg1.f3_deterministic(); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where +Warnings: +Note 1003 select 'Deterministic package function' AS "Deterministic package function",count(0) AS "COUNT(*)" from "test"."t1" where "test"."t1"."c1" = ("test"."pkg1"."f3_deterministic"()) +EXPLAIN EXTENDED SELECT 'Non-deterministic package function', COUNT(*) FROM t1 WHERE c1 = pkg1.f4_not_deterministic(); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where +Warnings: +Note 1003 select 'Non-deterministic package function' AS "Non-deterministic package function",count(0) AS "COUNT(*)" from "test"."t1" where "test"."t1"."c1" = "test"."pkg1"."f4_not_deterministic"() +DROP TABLE t1; +DROP FUNCTION f1_deterministic; +DROP FUNCTION f2_not_deterministic; +DROP PACKAGE pkg1; diff --git a/mysql-test/suite/compat/oracle/t/sp-package.test b/mysql-test/suite/compat/oracle/t/sp-package.test index 401a46ad206..4a44872dd6f 100644 --- a/mysql-test/suite/compat/oracle/t/sp-package.test +++ b/mysql-test/suite/compat/oracle/t/sp-package.test @@ -3016,3 +3016,75 @@ CALL db2.pkg1.p2_db1_pkg1_p1; DROP DATABASE db1; DROP DATABASE db2; + + +--echo # +--echo # MDEV-29370 Functions in packages are slow and seems to ignore deterministic +--echo # + +SET SQL_MODE=ORACLE; + +CREATE TABLE t1 (c1 CHAR(1)); + +DELIMITER //; +CREATE FUNCTION f1_deterministic() +RETURN CHAR(1) +DETERMINISTIC +IS +BEGIN + RETURN 'X'; +END; +// + +CREATE FUNCTION f2_not_deterministic() +RETURN CHAR(1) +IS +BEGIN + RETURN 'X'; +END; +// + +CREATE PACKAGE pkg1 +IS + PROCEDURE t1_populate(numrows INTEGER); + FUNCTION f3_deterministic() RETURN CHAR(1) DETERMINISTIC; + FUNCTION f4_not_deterministic() RETURN CHAR(1); +END; +// + +CREATE PACKAGE BODY pkg1 +IS + PROCEDURE t1_populate(numrounds INTEGER) + IS + i INTEGER; + BEGIN + INSERT INTO t1 VALUES('Y'); + FOR i IN 1..numrounds LOOP + INSERT INTO t1 SELECT * FROM t1; + END LOOP; + END; + FUNCTION f3_deterministic() RETURN CHAR(1) DETERMINISTIC COMMENT 'xxx' + IS + BEGIN + RETURN 'X'; + END; + FUNCTION f4_not_deterministic() RETURN CHAR(1) + IS + BEGIN + RETURN 'X'; + END; +END; +// +DELIMITER ;// + +CALL pkg1.t1_populate(3); + +EXPLAIN EXTENDED SELECT 'Deterministic function', COUNT(*) FROM t1 WHERE c1 = f1_deterministic(); +EXPLAIN EXTENDED SELECT 'Non-deterministic function', COUNT(*) FROM t1 WHERE c1 = f2_not_deterministic(); +EXPLAIN EXTENDED SELECT 'Deterministic package function', COUNT(*) FROM t1 WHERE c1 = pkg1.f3_deterministic(); +EXPLAIN EXTENDED SELECT 'Non-deterministic package function', COUNT(*) FROM t1 WHERE c1 = pkg1.f4_not_deterministic(); + +DROP TABLE t1; +DROP FUNCTION f1_deterministic; +DROP FUNCTION f2_not_deterministic; +DROP PACKAGE pkg1; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 57e67bed3cb..cdd724b8654 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -18833,6 +18833,7 @@ package_implementation_function_body: sp_head *sp= pkg->m_current_routine->sphead; thd->lex= pkg->m_current_routine; sp->reset_thd_mem_root(thd); + sp->set_c_chistics(thd->lex->sp_chistics); sp->set_body_start(thd, YYLIP->get_cpp_tok_start()); } sp_body opt_package_routine_end_name @@ -18851,6 +18852,7 @@ package_implementation_procedure_body: sp_head *sp= pkg->m_current_routine->sphead; thd->lex= pkg->m_current_routine; sp->reset_thd_mem_root(thd); + sp->set_c_chistics(thd->lex->sp_chistics); sp->set_body_start(thd, YYLIP->get_cpp_tok_start()); } sp_body opt_package_routine_end_name From 0b25551a61878efb73e8b7802edf5cc69224846c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 15 Nov 2022 16:56:13 +0200 Subject: [PATCH 2/4] MDEV-29999 innodb_undo_log_truncate=ON is not crash safe If a log checkpoint occurs at the end LSN of mtr.commit_shrink(space) in trx_purge_truncate_history(), then recovery may fail because it could try to apply too old log records to too old copies of undo log pages. This was repeated with the following test: ./mtr innodb.undo_log_truncate,4k,strict_full_crc32 recv_sys_t::trim(): Move some code to the caller. recv_sys_t::apply(): For undo tablespace truncation, discard all old redo log for the undo tablespace, and then truncate the file to the desired size. Tested by: Matthias Leich --- storage/innobase/log/log0recv.cc | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 8c8d87b974c..826ddf3ff49 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -745,14 +745,6 @@ inline void recv_sys_t::trim(const page_id_t page_id, lsn_t lsn) pages.erase(r); } } - if (fil_space_t* space = fil_space_get(page_id.space())) { - ut_ad(UT_LIST_GET_LEN(space->chain) == 1); - fil_node_t* file = UT_LIST_GET_FIRST(space->chain); - ut_ad(file->is_open()); - os_file_truncate(file->name, file->handle, - os_offset_t{page_id.page_no()} - << srv_page_size_shift, true); - } DBUG_VOID_RETURN; } @@ -2694,7 +2686,17 @@ void recv_sys_t::apply(bool last_batch) { const trunc& t= truncated_undo_spaces[id]; if (t.lsn) - trim(page_id_t(id + srv_undo_space_id_start, t.pages), t.lsn); + { + trim(page_id_t(id + srv_undo_space_id_start, 0), t.lsn); + if (fil_space_t *space = fil_space_get(id + srv_undo_space_id_start)) + { + ut_ad(UT_LIST_GET_LEN(space->chain) == 1); + fil_node_t *file= UT_LIST_GET_FIRST(space->chain); + ut_ad(file->is_open()); + os_file_truncate(file->name, file->handle, + os_offset_t{t.pages} << srv_page_size_shift, true); + } + } } fil_system.extend_to_recv_size(); From 4b3b1eb810f81cf8947500129eb25c129fabc629 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 16 Nov 2022 13:46:24 +0100 Subject: [PATCH 3/4] MDEV-25625 Test sys_vars.wsrep_on_without_provider fails: mysqltest: At line 8: query 'SET GLOBAL wsrep_on=ON' failed with wrong errno 1193: 'Unknown system variable 'wsrep_on'', instead of 1210... --- mysql-test/suite/sys_vars/t/wsrep_on_without_provider.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/sys_vars/t/wsrep_on_without_provider.test b/mysql-test/suite/sys_vars/t/wsrep_on_without_provider.test index 5bee3c9a356..9b32552436f 100644 --- a/mysql-test/suite/sys_vars/t/wsrep_on_without_provider.test +++ b/mysql-test/suite/sys_vars/t/wsrep_on_without_provider.test @@ -1,4 +1,5 @@ --source include/not_embedded.inc +--source include/have_wsrep.inc # # @@global.wsrep_on is not allowed if there From 41028d70f6e4ec866775bc8f9d00739ad3dbe0c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 17 Nov 2022 08:33:05 +0200 Subject: [PATCH 4/4] MDEV-29982 fixup: Relax the test The log overwrite warnings are not being reliably emitted in all debug-instrumented environments. It may be related to the scheduling of some InnoDB internal activity, such as the purging of committed transaction history. --- mysql-test/suite/encryption/r/innochecksum,debug.rdiff | 10 ---------- mysql-test/suite/encryption/t/innochecksum.test | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 mysql-test/suite/encryption/r/innochecksum,debug.rdiff diff --git a/mysql-test/suite/encryption/r/innochecksum,debug.rdiff b/mysql-test/suite/encryption/r/innochecksum,debug.rdiff deleted file mode 100644 index c3e3eed26bd..00000000000 --- a/mysql-test/suite/encryption/r/innochecksum,debug.rdiff +++ /dev/null @@ -1,10 +0,0 @@ -@@ -30,6 +30,9 @@ - # Space ID mismatch - # Restore the original tables - # Corrupt FIL_DATA+10 (data) -+# FOUND 1 is expected for both. -+FOUND 1 /InnoDB: Crash recovery is broken due to insufficient innodb_log_file_size; last checkpoint LSN=\d+, current LSN=\d+\. Shutdown is in progress\..*InnoDB: Crash recovery was broken.*/ in mysqld.1.err -+FOUND 1 /InnoDB: Crash recovery was broken/ in mysqld.1.err - # Run innochecksum on t2 - # Run innochecksum on t3 - # Run innochecksum on t6 diff --git a/mysql-test/suite/encryption/t/innochecksum.test b/mysql-test/suite/encryption/t/innochecksum.test index ecabce30ab7..516bc0733d9 100644 --- a/mysql-test/suite/encryption/t/innochecksum.test +++ b/mysql-test/suite/encryption/t/innochecksum.test @@ -264,7 +264,7 @@ print FILE pack("H*", "c00lcafedeadb017"); close FILE or die "close"; EOF -if ($have_debug) { +if (0 && $have_debug) { # these messages sometimes fail to appear --let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err --let SEARCH_PATTERN= InnoDB: Crash recovery is broken due to insufficient innodb_log_file_size; last checkpoint LSN=\\d+, current LSN=\\d+\\. Shutdown is in progress\\..*InnoDB: Crash recovery was broken.* --echo # FOUND 1 is expected for both.