diff --git a/debian/mariadb-test.install b/debian/mariadb-test.install index 5dda38d665c..b9d99885374 100644 --- a/debian/mariadb-test.install +++ b/debian/mariadb-test.install @@ -26,6 +26,7 @@ usr/lib/mysql/plugin/qa_auth_interface.so usr/lib/mysql/plugin/qa_auth_server.so usr/lib/mysql/plugin/test_sql_service.so usr/lib/mysql/plugin/test_versioning.so +usr/lib/mysql/plugin/type_mysql_timestamp.so usr/share/man/man1/mariadb-client-test-embedded.1 usr/share/man/man1/mariadb-client-test.1 usr/share/man/man1/mariadb-test-embedded.1 diff --git a/mysql-test/main/create_w_max_indexes_128.result b/mysql-test/main/create_w_max_indexes_128.result index d86bc912e58..112df1b7c41 100644 --- a/mysql-test/main/create_w_max_indexes_128.result +++ b/mysql-test/main/create_w_max_indexes_128.result @@ -470,7 +470,7 @@ t1 CREATE TABLE `t1` ( KEY `a126_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a127_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a128_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci flush tables; show create table t1; Table Create Table @@ -619,7 +619,7 @@ t1 CREATE TABLE `t1` ( KEY `a126_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a127_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a128_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; create table t1 (c1 int, c2 int, c3 int, c4 int, c5 int, c6 int, c7 int, c8 int, c9 int, c10 int, c11 int, c12 int, c13 int, c14 int, c15 int, c16 int); @@ -1092,7 +1092,7 @@ t1 CREATE TABLE `t1` ( KEY `a126_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a127_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a128_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci flush tables; show create table t1; Table Create Table @@ -1241,7 +1241,7 @@ t1 CREATE TABLE `t1` ( KEY `a126_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a127_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`), KEY `a128_long_123456789_123456789_123456789_123456789_123456789_1234` (`c1`,`c2`,`c3`,`c4`,`c5`,`c6`,`c7`,`c8`,`c9`,`c10`,`c11`,`c12`,`c13`,`c14`,`c15`,`c16`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci alter table t1 add key a129_long_123456789_123456789_123456789_123456789_123456789_1234 ( c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16); diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index 33afb47e4dd..d516e3fe522 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -20787,6 +20787,100 @@ a deallocate prepare stmt; drop view v1; drop table t1; +# +# MDEV-31240: condition pushed into splittable derived has reference to +# outer column and does not refer to any column of embedding +# select +# +create table t1 (a int); +insert into t1 select seq from seq_1_to_1000; +create table t2 (a int, b int, key (a)); +insert into t2 select mod(seq,100), rand(13) * mod(seq,500) from seq_1_to_1000; +create table t3 (a int); +insert into t3 values (3), (1); +analyze table t1, t2, t3 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status Table is already up to date +test.t3 analyze status Engine-independent statistics collected +test.t3 analyze status OK +explain select +a, +( select concat(t3.a,'=',dt.s) +from +(select a, sum(b) as s from t2 group by a) as dt, +t3 +where dt.a=t1.a and t3.a < 3 +) +from t1 limit 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 1000 +2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY ref key0 key0 5 test.t1.a 2 +3 LATERAL DERIVED t2 ref a a 5 test.t1.a 10 +select +a, +( select concat(t3.a,'=',dt.s) +from +(select a, sum(b) as s from t2 group by a) as dt, +t3 +where dt.a=t1.a and t3.a < 3 +) +from t1 limit 5; +a ( select concat(t3.a,'=',dt.s) +from +(select a, sum(b) as s from t2 group by a) as dt, +t3 +where dt.a=t1.a and t3.a < 3 +) +1 1=804 +2 1=1056 +3 1=846 +4 1=947 +5 1=973 +truncate table t2; +insert into t2 select mod(seq,10), rand(15) * mod(seq,500) from seq_1_to_1000; +analyze table t2 persistent for all; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status Table is already up to date +explain select +a, +( select concat(t3.a,'=',dt.s) +from +(select a, sum(b) as s from t2 group by a) as dt, +t3 +where dt.a=t1.a and t3.a < 3 +) +from t1 limit 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 1000 +2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY ref key0 key0 5 test.t1.a 100 +3 DERIVED t2 ALL a NULL NULL NULL 1000 Using temporary; Using filesort +select +a, +( select concat(t3.a,'=',dt.s) +from +(select a, sum(b) as s from t2 group by a) as dt, +t3 +where dt.a=t1.a and t3.a < 3 +) +from t1 limit 5; +a ( select concat(t3.a,'=',dt.s) +from +(select a, sum(b) as s from t2 group by a) as dt, +t3 +where dt.a=t1.a and t3.a < 3 +) +1 1=11858 +2 1=11380 +3 1=11588 +4 1=11373 +5 1=11612 +drop table t1,t2,t3; # End of 10.4 tests # # MDEV-28958: condition pushable into view after simplification diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test index 06b15f75a0b..7c87785ccc1 100644 --- a/mysql-test/main/derived_cond_pushdown.test +++ b/mysql-test/main/derived_cond_pushdown.test @@ -3973,6 +3973,47 @@ deallocate prepare stmt; drop view v1; drop table t1; +--echo # +--echo # MDEV-31240: condition pushed into splittable derived has reference to +--echo # outer column and does not refer to any column of embedding +--echo # select +--echo # + +create table t1 (a int); +insert into t1 select seq from seq_1_to_1000; + +create table t2 (a int, b int, key (a)); +insert into t2 select mod(seq,100), rand(13) * mod(seq,500) from seq_1_to_1000; + +create table t3 (a int); +insert into t3 values (3), (1); + +analyze table t1, t2, t3 persistent for all; + +let $q= +select + a, + ( select concat(t3.a,'=',dt.s) + from + (select a, sum(b) as s from t2 group by a) as dt, + t3 + where dt.a=t1.a and t3.a < 3 + ) +from t1 limit 5; + +eval explain $q; +eval $q; + +truncate table t2; +insert into t2 select mod(seq,10), rand(15) * mod(seq,500) from seq_1_to_1000; + +analyze table t2 persistent for all; + +eval explain $q; +eval $q; + +drop table t1,t2,t3; + --echo # End of 10.4 tests --echo # diff --git a/mysql-test/main/derived_split_innodb.result b/mysql-test/main/derived_split_innodb.result index aba4f88493c..aba9ae85622 100644 --- a/mysql-test/main/derived_split_innodb.result +++ b/mysql-test/main/derived_split_innodb.result @@ -839,5 +839,20 @@ SELECT t1.* FROM t1 JOIN (SELECT id, COUNT(*) FROM t2 GROUP BY id) sq ON sq.id= a set optimizer_switch= @tmp1, join_cache_level= @tmp2; DROP TABLE t1, t2; +# +# MDEV-31403: Server crashes in st_join_table::choose_best_splitting (still) +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15); +CREATE TABLE t2 (b INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (100),(200); +CREATE TABLE t3 (c INT, d INT, KEY(c)) ENGINE=InnoDB; +INSERT INTO t3 VALUES (1,1),(2,2); +CREATE VIEW v AS SELECT c, d FROM t3 GROUP BY c, d; +SELECT * FROM t1 JOIN t2 WHERE (t1.a, t2.b) IN (SELECT * FROM v); +a b +DROP VIEW v; +DROP TABLE t1, t2, t3; # End of 10.4 tests SET GLOBAL innodb_stats_persistent=@save_innodb_stats_persistent; diff --git a/mysql-test/main/derived_split_innodb.test b/mysql-test/main/derived_split_innodb.test index 6ccbc31d886..bccda42d778 100644 --- a/mysql-test/main/derived_split_innodb.test +++ b/mysql-test/main/derived_split_innodb.test @@ -466,6 +466,27 @@ set optimizer_switch= @tmp1, join_cache_level= @tmp2; # Cleanup DROP TABLE t1, t2; +--echo # +--echo # MDEV-31403: Server crashes in st_join_table::choose_best_splitting (still) +--echo # +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES + (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15); + +CREATE TABLE t2 (b INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (100),(200); + +CREATE TABLE t3 (c INT, d INT, KEY(c)) ENGINE=InnoDB; +INSERT INTO t3 VALUES (1,1),(2,2); + +CREATE VIEW v AS SELECT c, d FROM t3 GROUP BY c, d; + +SELECT * FROM t1 JOIN t2 WHERE (t1.a, t2.b) IN (SELECT * FROM v); + +# Cleanup +DROP VIEW v; +DROP TABLE t1, t2, t3; + --echo # End of 10.4 tests SET GLOBAL innodb_stats_persistent=@save_innodb_stats_persistent; diff --git a/mysql-test/main/explain_non_select.result b/mysql-test/main/explain_non_select.result index 03259fff62b..74d8103f130 100644 --- a/mysql-test/main/explain_non_select.result +++ b/mysql-test/main/explain_non_select.result @@ -277,3 +277,22 @@ EXECUTE stmt; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 2 drop table t1,t2; +# +# MDEV-31224: EXPLAIN EXTENDED for multi-table update of system table +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (3); +EXPLAIN EXTENDED UPDATE t1, t2 SET b = 4 WHERE a IN (6,2); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 system NULL NULL NULL NULL 1 100.00 +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 update `test`.`t1` set `test`.`t2`.`b` = 4 where `test`.`t1`.`a` in (6,2) +UPDATE t1, t2 SET b = 4 WHERE a IN (6,2); +SELECT * from t2; +b +4 +DROP TABLE t1, t2; +# End of 10.4 tests diff --git a/mysql-test/main/explain_non_select.test b/mysql-test/main/explain_non_select.test index d9ff0fb7245..f87a5d9ec8d 100644 --- a/mysql-test/main/explain_non_select.test +++ b/mysql-test/main/explain_non_select.test @@ -250,3 +250,23 @@ PREPARE stmt FROM 'EXPLAIN INSERT INTO t1 SELECT * FROM t2'; EXECUTE stmt; drop table t1,t2; +--echo # +--echo # MDEV-31224: EXPLAIN EXTENDED for multi-table update of system table +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); + +CREATE TABLE t2 (b INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (3); + +let $q= +UPDATE t1, t2 SET b = 4 WHERE a IN (6,2); + +eval EXPLAIN EXTENDED $q; +eval $q; +SELECT * from t2; + +DROP TABLE t1, t2; + +--echo # End of 10.4 tests diff --git a/mysql-test/main/group_min_max.result b/mysql-test/main/group_min_max.result index 055bd266e15..a8605e6dd58 100644 --- a/mysql-test/main/group_min_max.result +++ b/mysql-test/main/group_min_max.result @@ -4204,6 +4204,30 @@ a b s1 2 2 t2:t2a-null;min_t3_b:t3b-null 3 3 t2:1;min_t3_b:3 drop table t1,t2,t3; +# +# MDEV-31380: Assertion `s->table->opt_range_condition_rows <= s->found_records' failed +# (assertion in 10.6+, DBL_MAX costs in 10.5) +# +CREATE TABLE t1 (a INT, b INT, PRIMARY KEY(a), KEY(b)) ENGINE=InnoDB; +INSERT INTO t1 SELECT seq, seq FROM seq_1_to_100; +SET +@tmp=@@optimizer_use_condition_selectivity, +optimizer_use_condition_selectivity = 1, +@tmp2=@@optimizer_trace, +optimizer_trace=1; +SELECT DISTINCT * FROM t1 WHERE a IN (1, 2); +a b +1 1 +2 2 +select +CAST(json_value(json_extract(trace, '$**.chosen_access_method.cost'), '$[0]') +as DOUBLE) < 1.0e100 +from information_schema.optimizer_trace; +CAST(json_value(json_extract(trace, '$**.chosen_access_method.cost'), '$[0]') +as DOUBLE) < 1.0e100 +1 +set optimizer_use_condition_selectivity = @tmp, optimizer_trace=@tmp2; +drop table t1; # # End of 10.5 tests # diff --git a/mysql-test/main/group_min_max.test b/mysql-test/main/group_min_max.test index 9d056473537..5d6f555d33c 100644 --- a/mysql-test/main/group_min_max.test +++ b/mysql-test/main/group_min_max.test @@ -7,6 +7,7 @@ --source include/default_optimizer_switch.inc --source include/have_sequence.inc --source include/have_innodb.inc +--source include/have_sequence.inc # # TODO: # Add queries with: @@ -1859,6 +1860,30 @@ from t1; drop table t1,t2,t3; +--echo # +--echo # MDEV-31380: Assertion `s->table->opt_range_condition_rows <= s->found_records' failed +--echo # (assertion in 10.6+, DBL_MAX costs in 10.5) +--echo # + +CREATE TABLE t1 (a INT, b INT, PRIMARY KEY(a), KEY(b)) ENGINE=InnoDB; +INSERT INTO t1 SELECT seq, seq FROM seq_1_to_100; + +SET + @tmp=@@optimizer_use_condition_selectivity, + optimizer_use_condition_selectivity = 1, + @tmp2=@@optimizer_trace, + optimizer_trace=1; + +SELECT DISTINCT * FROM t1 WHERE a IN (1, 2); + +select + CAST(json_value(json_extract(trace, '$**.chosen_access_method.cost'), '$[0]') + as DOUBLE) < 1.0e100 +from information_schema.optimizer_trace; + +set optimizer_use_condition_selectivity = @tmp, optimizer_trace=@tmp2; +drop table t1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result index 210679ba29e..61fa42d1596 100644 --- a/mysql-test/main/myisam_explain_non_select_all.result +++ b/mysql-test/main/myisam_explain_non_select_all.result @@ -2689,7 +2689,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 system NULL NULL NULL NULL 0 0.00 Const row not found 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Warnings: -Note 1003 update `test`.`t1` set NULL = 10 +Note 1003 update `test`.`t1` set `test`.`t2`.`c2` = 10 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 7 @@ -2734,7 +2734,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 system NULL NULL NULL NULL 0 0.00 Const row not found 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 update `test`.`t1` set NULL = 10 where `test`.`t1`.`c3` = 10 +Note 1003 update `test`.`t1` set `test`.`t2`.`c2` = 10 where `test`.`t1`.`c3` = 10 # Status of EXPLAIN EXTENDED query Variable_name Value Handler_read_key 7 diff --git a/mysql-test/suite/galera/r/MDEV-24143.result b/mysql-test/suite/galera/r/MDEV-24143.result new file mode 100644 index 00000000000..860d8a35834 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-24143.result @@ -0,0 +1,23 @@ +connection node_2; +connection node_1; +CREATE TABLE t1 (c1 BIGINT NOT NULL PRIMARY KEY, c2 BINARY (10), c3 DATETIME); +SELECT get_lock ('test2', 0); +get_lock ('test2', 0) +1 +DROP TABLE t1; +CREATE TABLE t1 (c1 SMALLINT NOT NULL AUTO_INCREMENT PRIMARY KEY); +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_trx_fragment_size=10; +SET SESSION autocommit=0; +SELECT * FROM t1 WHERE c1 <=0 ORDER BY c1 DESC; +c1 +INSERT INTO t1 VALUES (4),(3),(1),(2); +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +CREATE TABLE t1 (pk INT PRIMARY KEY, b INT) ENGINE=SEQUENCE; +ERROR 42S01: Table 't1' already exists +ALTER TABLE t1 DROP COLUMN c2; +ERROR 42000: Can't DROP COLUMN `c2`; check that it exists +SELECT get_lock ('test', 1.5); +get_lock ('test', 1.5) +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result b/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result new file mode 100644 index 00000000000..0ef2a1a72c6 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_bf_abort_get_lock.result @@ -0,0 +1,18 @@ +connection node_2; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +connection node_2a; +SELECT GET_LOCK("foo", 1000); +GET_LOCK("foo", 1000) +1 +connection node_2; +SET AUTOCOMMIT=OFF; +INSERT INTO t1 VALUES (1); +SELECT GET_LOCK("foo", 1000);; +connection node_1; +INSERT INTO t1 VALUES (1); +connection node_2; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +wsrep_local_aborts_increment +1 +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_locks_funcs.result b/mysql-test/suite/galera/r/galera_locks_funcs.result deleted file mode 100644 index 25d3bbe28f5..00000000000 --- a/mysql-test/suite/galera/r/galera_locks_funcs.result +++ /dev/null @@ -1,24 +0,0 @@ -connection node_2; -connection node_1; -CREATE TABLE t (c DOUBLE,c2 INT,PRIMARY KEY(c)) ENGINE=InnoDB; -INSERT INTO t values (1,1); -SELECT GET_LOCK('a',1); -ERROR 42000: This version of MariaDB doesn't yet support 'GET_LOCK in cluster (WSREP_ON=ON)' -SHOW WARNINGS; -Level Code Message -Error 1235 This version of MariaDB doesn't yet support 'GET_LOCK in cluster (WSREP_ON=ON)' -SELECT * FROM t; -c c2 -1 1 -SELECT RELEASE_LOCK('a'); -ERROR 42000: This version of MariaDB doesn't yet support 'RELEASE_LOCK in cluster (WSREP_ON=ON)' -SHOW WARNINGS; -Level Code Message -Error 1235 This version of MariaDB doesn't yet support 'RELEASE_LOCK in cluster (WSREP_ON=ON)' -SELECT RELEASE_ALL_LOCKS(); -ERROR 42000: This version of MariaDB doesn't yet support 'RELEASE_ALL_LOCKS in cluster (WSREP_ON=ON)' -SHOW WARNINGS; -Level Code Message -Error 1235 This version of MariaDB doesn't yet support 'RELEASE_ALL_LOCKS in cluster (WSREP_ON=ON)' -COMMIT; -DROP TABLE t; diff --git a/mysql-test/suite/galera/t/MDEV-24143.test b/mysql-test/suite/galera/t/MDEV-24143.test new file mode 100644 index 00000000000..e58f147cb7c --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-24143.test @@ -0,0 +1,20 @@ +--source include/galera_cluster.inc +--source include/have_sequence.inc + +CREATE TABLE t1 (c1 BIGINT NOT NULL PRIMARY KEY, c2 BINARY (10), c3 DATETIME); +SELECT get_lock ('test2', 0); +DROP TABLE t1; +CREATE TABLE t1 (c1 SMALLINT NOT NULL AUTO_INCREMENT PRIMARY KEY); +INSERT INTO t1 VALUES (1); +SET SESSION wsrep_trx_fragment_size=10; +SET SESSION autocommit=0; +SELECT * FROM t1 WHERE c1 <=0 ORDER BY c1 DESC; +--error ER_LOCK_DEADLOCK +INSERT INTO t1 VALUES (4),(3),(1),(2); +--error ER_TABLE_EXISTS_ERROR +CREATE TABLE t1 (pk INT PRIMARY KEY, b INT) ENGINE=SEQUENCE; +--error ER_CANT_DROP_FIELD_OR_KEY +ALTER TABLE t1 DROP COLUMN c2; +SELECT get_lock ('test', 1.5); +DROP TABLE t1; + diff --git a/mysql-test/suite/galera/t/galera_bf_abort_get_lock.test b/mysql-test/suite/galera/t/galera_bf_abort_get_lock.test new file mode 100644 index 00000000000..72fc1c5b583 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_abort_get_lock.test @@ -0,0 +1,36 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# +# Test a local transaction being aborted by a slave one while it is running a GET_LOCK() +# + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--let $galera_connection_name = node_2a +--let $galera_server_number = 2 +--source include/galera_connect.inc +--connection node_2a +SELECT GET_LOCK("foo", 1000); + +--connection node_2 +SET AUTOCOMMIT=OFF; +--let $wsrep_local_bf_aborts_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` +INSERT INTO t1 VALUES (1); +--send SELECT GET_LOCK("foo", 1000); + +--connection node_1 +INSERT INTO t1 VALUES (1); + +--connection node_2 +--error ER_LOCK_DEADLOCK +--reap + +--let $wsrep_local_bf_aborts_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_bf_aborts'` + +# Check that wsrep_local_bf_aborts has been incremented by exactly 1 +--disable_query_log +--eval SELECT $wsrep_local_bf_aborts_after - $wsrep_local_bf_aborts_before = 1 AS wsrep_local_aborts_increment; +--enable_query_log + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_locks_funcs.test b/mysql-test/suite/galera/t/galera_locks_funcs.test deleted file mode 100644 index 42838e9585c..00000000000 --- a/mysql-test/suite/galera/t/galera_locks_funcs.test +++ /dev/null @@ -1,18 +0,0 @@ ---source include/galera_cluster.inc - -CREATE TABLE t (c DOUBLE,c2 INT,PRIMARY KEY(c)) ENGINE=InnoDB; -INSERT INTO t values (1,1); ---error ER_NOT_SUPPORTED_YET -SELECT GET_LOCK('a',1); -SHOW WARNINGS; -SELECT * FROM t; ---error ER_NOT_SUPPORTED_YET -SELECT RELEASE_LOCK('a'); -SHOW WARNINGS; -# New in 10.5 ---error ER_NOT_SUPPORTED_YET -SELECT RELEASE_ALL_LOCKS(); -SHOW WARNINGS; -COMMIT; -DROP TABLE t; - diff --git a/mysql-test/suite/gcol/r/gcol_purge.result b/mysql-test/suite/gcol/r/gcol_purge.result index 11063c7cd6f..a130485f219 100644 --- a/mysql-test/suite/gcol/r/gcol_purge.result +++ b/mysql-test/suite/gcol/r/gcol_purge.result @@ -16,7 +16,7 @@ INSERT INTO t1 (f1, f2) VALUES(1,2); set global debug_dbug="+d,ib_purge_virtual_index_callback"; connection con1; COMMIT; -InnoDB 0 transactions not purged +SET GLOBAL innodb_max_purge_lag_wait=1; connection con2; commit; disconnect con1; diff --git a/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result b/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result index 3f3b2db8f32..89711a2d8bb 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result @@ -78,7 +78,7 @@ SET DEBUG_SYNC= 'now WAIT_FOR uncommitted'; # enable purge COMMIT; # wait for purge to process the deleted records. -InnoDB 0 transactions not purged +InnoDB 1 transactions not purged SET DEBUG_SYNC= 'now SIGNAL purged'; connection default; /* connection default */ ALTER TABLE t1 ADD COLUMN c INT GENERATED ALWAYS AS(a+b), ADD INDEX idx (c), ALGORITHM=INPLACE, LOCK=SHARED; diff --git a/mysql-test/suite/gcol/t/gcol_purge.test b/mysql-test/suite/gcol/t/gcol_purge.test index ecfd89f4469..8fff375cdc2 100644 --- a/mysql-test/suite/gcol/t/gcol_purge.test +++ b/mysql-test/suite/gcol/t/gcol_purge.test @@ -23,7 +23,7 @@ set global debug_dbug="+d,ib_purge_virtual_index_callback"; connection con1; COMMIT; ---source ../innodb/include/wait_all_purged.inc +SET GLOBAL innodb_max_purge_lag_wait=1; connection con2; commit; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test index d9b764a75a7..e7bf8eb485b 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test @@ -113,7 +113,9 @@ SET DEBUG_SYNC= 'now WAIT_FOR uncommitted'; COMMIT; --echo # wait for purge to process the deleted records. +let $wait_all_purged = 1; --source ../../innodb/include/wait_all_purged.inc +let $wait_all_purged = 0; SET DEBUG_SYNC= 'now SIGNAL purged'; diff --git a/mysql-test/suite/innodb/r/cursor-restore-locking.result b/mysql-test/suite/innodb/r/cursor-restore-locking.result index 48263151ceb..6259cfd58ca 100644 --- a/mysql-test/suite/innodb/r/cursor-restore-locking.result +++ b/mysql-test/suite/innodb/r/cursor-restore-locking.result @@ -1,31 +1,34 @@ SET @save_freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency=1; -CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB; +CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB, STATS_PERSISTENT=0; InnoDB 0 transactions not purged connect prevent_purge,localhost,root,,; start transaction with consistent snapshot; connect con_del_1,localhost,root,,; INSERT INTO t VALUES (20,20); SET DEBUG_SYNC = 'innodb_row_search_for_mysql_exit SIGNAL first_del_row_search_mvcc_finished WAIT_FOR first_del_cont'; -DELETE FROM t WHERE b = 20; +DELETE FROM t WHERE b = 20 # trx_1; connect con_ins_1,localhost,root,,; SET DEBUG_SYNC = 'now WAIT_FOR first_del_row_search_mvcc_finished'; SET DEBUG_SYNC = 'lock_wait_start SIGNAL first_ins_locked'; SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR first_ins_cont'; -INSERT INTO t VALUES(10, 20); +INSERT INTO t VALUES(10, 20) # trx_2; connect con_del_2,localhost,root,,; SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET DEBUG_SYNC = 'now WAIT_FOR first_ins_locked'; SET DEBUG_SYNC = 'lock_wait_start SIGNAL second_del_locked'; -DELETE FROM t WHERE b = 20; +DELETE FROM t WHERE b = 20 # trx_3; connection default; SET DEBUG_SYNC = 'now WAIT_FOR second_del_locked'; +SET @saved_dbug = @@GLOBAL.debug_dbug; +SET @@GLOBAL.debug_dbug="d,enable_row_purge_del_mark_exit_sync_point"; SET DEBUG_SYNC = 'now SIGNAL first_del_cont'; SET DEBUG_SYNC = 'now WAIT_FOR first_ins_row_inserted'; connection con_del_1; connection default; disconnect prevent_purge; -InnoDB 0 transactions not purged +SET DEBUG_SYNC = 'now WAIT_FOR row_purge_del_mark_finished'; +SET @@GLOBAL.debug_dbug = @saved_dbug; SET DEBUG_SYNC = 'now SIGNAL first_ins_cont'; connection con_del_2; connection con_ins_1; diff --git a/mysql-test/suite/innodb/r/dml_purge.result b/mysql-test/suite/innodb/r/dml_purge.result index 38273d571c0..75a5f0fec6c 100644 --- a/mysql-test/suite/innodb/r/dml_purge.result +++ b/mysql-test/suite/innodb/r/dml_purge.result @@ -19,7 +19,7 @@ BEGIN; UPDATE t1 SET b=4 WHERE a=3; disconnect prevent_purge; connection default; -InnoDB 0 transactions not purged +SET GLOBAL innodb_max_purge_lag_wait=1; connection con1; ROLLBACK; disconnect con1; diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result index 5f74c234260..0b6d44aedc3 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug.result +++ b/mysql-test/suite/innodb/r/instant_alter_debug.result @@ -390,11 +390,12 @@ connection stop_purge; COMMIT; disconnect stop_purge; connection default; -InnoDB 0 transactions not purged +InnoDB 1 transactions not purged SET DEBUG_SYNC='now SIGNAL s2'; connection dml; disconnect dml; connection default; +InnoDB 0 transactions not purged SET DEBUG_SYNC=RESET; DROP TABLE t1; # End of 10.3 tests diff --git a/mysql-test/suite/innodb/r/instant_alter_purge.result b/mysql-test/suite/innodb/r/instant_alter_purge.result index 1179ff62ecc..261356bad12 100644 --- a/mysql-test/suite/innodb/r/instant_alter_purge.result +++ b/mysql-test/suite/innodb/r/instant_alter_purge.result @@ -1,5 +1,6 @@ SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency=1; +InnoDB 0 transactions not purged # # MDEV-17793 Crash in purge after instant DROP and emptying the table # @@ -16,7 +17,7 @@ COMMIT; START TRANSACTION WITH CONSISTENT SNAPSHOT; connection default; ALTER TABLE t1 ADD COLUMN extra TINYINT UNSIGNED NOT NULL DEFAULT 42; -InnoDB 1 transactions not purged +SET GLOBAL innodb_max_purge_lag_wait=1; ALTER TABLE t1 DROP extra; disconnect prevent_purge; InnoDB 0 transactions not purged diff --git a/mysql-test/suite/innodb/t/cursor-restore-locking.test b/mysql-test/suite/innodb/t/cursor-restore-locking.test index f8d00f57a5e..b65d3773ba2 100644 --- a/mysql-test/suite/innodb/t/cursor-restore-locking.test +++ b/mysql-test/suite/innodb/t/cursor-restore-locking.test @@ -5,7 +5,7 @@ source include/have_debug_sync.inc; SET @save_freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency=1; -CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB; +CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB, STATS_PERSISTENT=0; --source include/wait_all_purged.inc --connect(prevent_purge,localhost,root,,) @@ -14,20 +14,20 @@ start transaction with consistent snapshot; --connect(con_del_1,localhost,root,,) INSERT INTO t VALUES (20,20); SET DEBUG_SYNC = 'innodb_row_search_for_mysql_exit SIGNAL first_del_row_search_mvcc_finished WAIT_FOR first_del_cont'; ---send DELETE FROM t WHERE b = 20 +--send DELETE FROM t WHERE b = 20 # trx_1 --connect(con_ins_1,localhost,root,,) SET DEBUG_SYNC = 'now WAIT_FOR first_del_row_search_mvcc_finished'; # It's supposed the following INSERT will be suspended just after # lock_wait_start syncpoint, and will be awaken -# after the previous DELETE commits. ib_after_row_insert will be executed -# after the INSERT is woken up. The previous DELETE will wait for +# after trx_1 DELETE commits. ib_after_row_insert will be executed +# after the trx_2 INSERT is woken up. The trx_1 DELETE will wait for # first_del_cont signal before commit, and this signal will be sent later. # So it's safe to use two signals in a row here, it's guaranted the first # signal will be received before the second signal is sent. SET DEBUG_SYNC = 'lock_wait_start SIGNAL first_ins_locked'; SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR first_ins_cont'; ---send INSERT INTO t VALUES(10, 20) +--send INSERT INTO t VALUES(10, 20) # trx_2 --connect(con_del_2,localhost,root,,) # After MDEV-30225 is fixed, the following DELETE creates next-key lock for @@ -36,24 +36,26 @@ SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR fir SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET DEBUG_SYNC = 'now WAIT_FOR first_ins_locked'; SET DEBUG_SYNC = 'lock_wait_start SIGNAL second_del_locked'; -############################################################################### -# This DELETE is locked by the previous DELETE, after that DELETE is -# committed, it will still be locked by the next INSERT on delete-marked -# heap_no 2 record. After that INSERT inserted the record with heap_no 3, -# and after heap_no 2 record is purged, this DELETE will be unlocked and +############################################################################## +# trx_3 DELETE is locked by trx_1 DELETE, after trx_1 DELETE is +# committed, it will still be locked by trx_2 INSERT on delete-marked +# heap_no 2 record. After trx_2 INSERT inserted the record with heap_no 3, +# and after heap_no 2 record is purged, trx_3 DELETE will be unlocked and # must restore persistent cursor position at heap_no 3 record, as it has the # same secondary key value as former heap_no 2 record. Then it must be blocked -# by the previous INSERT, and after the INSERT is committed, it must -# delete the record, inserted by the previous INSERT, and the last INSERT(see +# by trx_2 INSERT, and after trx_2 INSERT is committed, it must +# delete the record, inserted by trx_2 INSERT, and trx_4 INSERT(see # below) must be finished without error. But instead this DELETE restores # persistent cursor position to supremum, as a result, it does not delete the -# record, inserted by the previous INSERT, and the last INSERT is finished with +# record, inserted by trx_2 INSERT, and trx_4 INSERT is finished with # duplicate key check error. ############################################################################### ---send DELETE FROM t WHERE b = 20 +--send DELETE FROM t WHERE b = 20 # trx_3 --connection default SET DEBUG_SYNC = 'now WAIT_FOR second_del_locked'; +SET @saved_dbug = @@GLOBAL.debug_dbug; +SET @@GLOBAL.debug_dbug="d,enable_row_purge_del_mark_exit_sync_point"; SET DEBUG_SYNC = 'now SIGNAL first_del_cont'; SET DEBUG_SYNC = 'now WAIT_FOR first_ins_row_inserted'; --connection con_del_1 @@ -61,7 +63,8 @@ SET DEBUG_SYNC = 'now WAIT_FOR first_ins_row_inserted'; --connection default --disconnect prevent_purge ---source include/wait_all_purged.inc +SET DEBUG_SYNC = 'now WAIT_FOR row_purge_del_mark_finished'; +SET @@GLOBAL.debug_dbug = @saved_dbug; SET DEBUG_SYNC = 'now SIGNAL first_ins_cont'; --connection con_del_2 @@ -74,7 +77,7 @@ SET DEBUG_SYNC = 'now SIGNAL first_ins_cont'; ############################################################################### # Duplicate key error is expected if the bug is not fixed. ############################################################################### -INSERT INTO t VALUES(30, 20); +INSERT INTO t VALUES(30, 20); # trx_4 --disconnect con_ins_1 --disconnect con_del_1 diff --git a/mysql-test/suite/innodb/t/dml_purge.test b/mysql-test/suite/innodb/t/dml_purge.test index 7034939aa4e..c13ff22572b 100644 --- a/mysql-test/suite/innodb/t/dml_purge.test +++ b/mysql-test/suite/innodb/t/dml_purge.test @@ -32,7 +32,7 @@ UPDATE t1 SET b=4 WHERE a=3; --connection default # Initiate a full purge, which should reset the DB_TRX_ID except for a=3. ---source include/wait_all_purged.inc +SET GLOBAL innodb_max_purge_lag_wait=1; # Initiate a ROLLBACK of the update, which should reset the DB_TRX_ID for a=3. --connection con1 ROLLBACK; diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test index c6eca884907..917226a6c26 100644 --- a/mysql-test/suite/innodb/t/instant_alter_debug.test +++ b/mysql-test/suite/innodb/t/instant_alter_debug.test @@ -450,7 +450,9 @@ COMMIT; disconnect stop_purge; connection default; +let $wait_all_purged = 1; --source include/wait_all_purged.inc +let $wait_all_purged = 0; SET DEBUG_SYNC='now SIGNAL s2'; connection dml; @@ -458,6 +460,7 @@ reap; disconnect dml; connection default; +--source include/wait_all_purged.inc SET DEBUG_SYNC=RESET; DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/instant_alter_purge.test b/mysql-test/suite/innodb/t/instant_alter_purge.test index 9ccf3347d7b..88a56141a1f 100644 --- a/mysql-test/suite/innodb/t/instant_alter_purge.test +++ b/mysql-test/suite/innodb/t/instant_alter_purge.test @@ -6,6 +6,7 @@ if ($have_debug) { SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency=1; +--source include/wait_all_purged.inc --echo # --echo # MDEV-17793 Crash in purge after instant DROP and emptying the table @@ -27,8 +28,7 @@ START TRANSACTION WITH CONSISTENT SNAPSHOT; connection default; ALTER TABLE t1 ADD COLUMN extra TINYINT UNSIGNED NOT NULL DEFAULT 42; -let $wait_all_purged= 1; ---source include/wait_all_purged.inc +SET GLOBAL innodb_max_purge_lag_wait=1; ALTER TABLE t1 DROP extra; disconnect prevent_purge; let $wait_all_purged= 0; diff --git a/mysql-test/suite/innodb/t/purge_secondary.test b/mysql-test/suite/innodb/t/purge_secondary.test index 1a0d178f66a..a7f75f56b53 100644 --- a/mysql-test/suite/innodb/t/purge_secondary.test +++ b/mysql-test/suite/innodb/t/purge_secondary.test @@ -1,6 +1,10 @@ --source include/have_innodb.inc --source include/have_sequence.inc +--disable_query_log +call mtr.add_suppression("InnoDB: Difficult to find free blocks in the buffer pool"); +--enable_query_log + # Ensure that the history list length will actually be decremented by purge. SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; diff --git a/sql/item_create.cc b/sql/item_create.cc index 5d28cfca111..2143ecaf6ac 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -3666,13 +3666,6 @@ Create_func_get_lock Create_func_get_lock::s_singleton; Item* Create_func_get_lock::create_2_arg(THD *thd, Item *arg1, Item *arg2) { -#ifdef WITH_WSREP - if (WSREP_ON && WSREP(thd)) - { - my_error(ER_NOT_SUPPORTED_YET, MYF(0), "GET_LOCK in cluster (WSREP_ON=ON)"); - return NULL; - } -#endif /* WITH_WSREP */ thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_func_get_lock(thd, arg1, arg2); @@ -4997,13 +4990,6 @@ Create_func_release_all_locks Create_func_release_all_locks::s_singleton; Item* Create_func_release_all_locks::create_builder(THD *thd) { -#ifdef WITH_WSREP - if (WSREP_ON && WSREP(thd)) - { - my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RELEASE_ALL_LOCKS in cluster (WSREP_ON=ON)"); - return NULL; - } -#endif /* WITH_WSREP */ thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_func_release_all_locks(thd); @@ -5015,13 +5001,6 @@ Create_func_release_lock Create_func_release_lock::s_singleton; Item* Create_func_release_lock::create_1_arg(THD *thd, Item *arg1) { -#ifdef WITH_WSREP - if (WSREP_ON && WSREP(thd)) - { - my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RELEASE_LOCK in cluster (WSREP_ON=ON)"); - return NULL; - } -#endif /* WITH_WSREP */ thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_func_release_lock(thd, arg1); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index a32d4cfe24e..e84a2a1b4a0 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3033,8 +3033,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, restore_nonrange_trees(¶m, tree, backup_keys); if ((group_trp= get_best_group_min_max(¶m, tree, read_time))) { - param.table->opt_range_condition_rows= MY_MIN(group_trp->records, - head->stat_records()); + set_if_smaller(param.table->opt_range_condition_rows, + group_trp->records); Json_writer_object grp_summary(thd, "best_group_range_summary"); if (unlikely(thd->trace_started())) diff --git a/sql/opt_split.cc b/sql/opt_split.cc index e00a26e3328..43cd5517b6c 100644 --- a/sql/opt_split.cc +++ b/sql/opt_split.cc @@ -664,7 +664,8 @@ add_ext_keyuse_for_splitting(Dynamic_array *ext_keyuses, keyuse_ext.cond_guard= added_key_field->cond_guard; keyuse_ext.sj_pred_no= added_key_field->sj_pred_no; keyuse_ext.validity_ref= 0; - keyuse_ext.needed_in_prefix= added_key_field->val->used_tables(); + keyuse_ext.needed_in_prefix= added_key_field->val->used_tables() & + ~(OUTER_REF_TABLE_BIT | RAND_TABLE_BIT); keyuse_ext.validity_var= false; return ext_keyuses->push(keyuse_ext); } @@ -945,6 +946,7 @@ void reset_validity_vars_for_keyuses(KEYUSE_EXT *key_keyuse_ext_start, SplM_plan_info * JOIN_TAB::choose_best_splitting(uint idx, table_map remaining_tables, + const POSITION *join_positions, table_map *spl_pd_boundary) { SplM_opt_info *spl_opt_info= table->spl_opt_info; @@ -1042,7 +1044,7 @@ SplM_plan_info * JOIN_TAB::choose_best_splitting(uint idx, else { table_map last_found= this->table->map; - for (POSITION *pos= &this->join->positions[idx - 1]; ; pos--) + for (const POSITION *pos= &join_positions[idx - 1]; ; pos--) { if (pos->table->table->map & excluded_tables) continue; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 363356eb385..699e8b7c2ee 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7935,6 +7935,7 @@ best_access_path(JOIN *join, if (s->table->is_splittable()) spl_plan= s->choose_best_splitting(idx, remaining_tables, + join_positions, &spl_pd_boundary); Json_writer_array trace_paths(thd, "considered_access_paths"); @@ -29079,7 +29080,7 @@ void st_select_lex::print_set_clause(THD *thd, String *str, else str->append(','); - item->print(str, query_type); + item->print(str, (enum_query_type) (query_type | QT_NO_DATA_EXPANSION)); str->append(STRING_WITH_LEN(" = ")); val->print(str, query_type); } diff --git a/sql/sql_select.h b/sql/sql_select.h index 1dc16cb8b74..f162907c393 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -700,6 +700,7 @@ typedef struct st_join_table { void add_keyuses_for_splitting(); SplM_plan_info *choose_best_splitting(uint idx, table_map remaining_tables, + const POSITION *join_positions, table_map *spl_pd_boundary); bool fix_splitting(SplM_plan_info *spl_plan, table_map excluded_tables, bool is_const_table); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index bd81e46d1e4..38e3090e4ca 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -19418,10 +19418,17 @@ static MYSQL_SYSVAR_ULONG(purge_rseg_truncate_frequency, " purge rollback segment(s) on every Nth iteration of purge invocation", NULL, NULL, 128, 1, 128, 0); +static void innodb_undo_log_truncate_update(THD *thd, struct st_mysql_sys_var*, + void*, const void *save) +{ + if ((srv_undo_log_truncate= *static_cast(save))) + srv_wake_purge_thread_if_not_active(); +} + static MYSQL_SYSVAR_BOOL(undo_log_truncate, srv_undo_log_truncate, PLUGIN_VAR_OPCMDARG, "Enable or Disable Truncate of UNDO tablespace.", - NULL, NULL, FALSE); + NULL, innodb_undo_log_truncate_update, FALSE); static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index bf6f6eb8eff..79b5c294e2a 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -39,13 +39,20 @@ Remove the undo log segment from the rseg slot if it is too big for reuse. @param[in,out] mtr mini-transaction */ void trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr); + +/** +Remove unnecessary history data from rollback segments. NOTE that when this +function is called, the caller (purge_coordinator_callback) +must not have any latches on undo log pages! +*/ +void trx_purge_truncate_history(); + /** Run a purge batch. @param n_tasks number of purge tasks to submit to the queue @param history_size trx_sys.history_size() -@param truncate whether to truncate the history at the end of the batch @return number of undo log pages handled in the batch */ -ulint trx_purge(ulint n_tasks, ulint history_size, bool truncate); +ulint trx_purge(ulint n_tasks, ulint history_size); /** Rollback segements from a given transaction with trx-no scheduled for purge. */ @@ -285,6 +292,18 @@ public: typically via purge_sys_t::view_guard. */ return view.low_limit_no(); } + /** A wrapper around ReadView::sees(). */ + trx_id_t sees(trx_id_t id) const + { + /* This function may only be called by purge_coordinator_callback(). + + The purge coordinator task may call this without holding any latch, + because it is the only thread that may modify purge_sys.view. + + Any other threads that access purge_sys.view must hold purge_sys.latch, + typically via purge_sys_t::view_guard. */ + return view.sees(id); + } /** A wrapper around trx_sys_t::clone_oldest_view(). */ template void clone_oldest_view() diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 3f62eb79aed..63edb96cd0a 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -47,6 +47,7 @@ Created 3/14/1997 Heikki Tuuri #include "handler.h" #include "ha_innodb.h" #include "fil0fil.h" +#include "debug_sync.h" #include /************************************************************************* @@ -631,7 +632,17 @@ row_purge_del_mark( mem_heap_free(heap); } - return row_purge_remove_clust_if_poss(node); + bool result= row_purge_remove_clust_if_poss(node); + +#ifdef ENABLED_DEBUG_SYNC + DBUG_EXECUTE_IF("enable_row_purge_del_mark_exit_sync_point", + debug_sync_set_action + (current_thd, + STRING_WITH_LEN("now SIGNAL row_purge_del_mark_finished")); + ); +#endif + + return result; } void purge_sys_t::wait_SYS() @@ -850,6 +861,9 @@ skip_secondaries: buf_page_get(page_id_t(rseg.space->id, page_no), 0, RW_X_LATCH, &mtr)) { + block->page.set_accessed(); + buf_page_make_young_if_needed(&block->page); + byte* data_field = block->page.frame + offset + internal_offset; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 3be254ee8d2..ed3ca194934 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1262,17 +1262,14 @@ static tpool::waitable_task purge_coordinator_task static tpool::timer *purge_coordinator_timer; /** Wake up the purge threads if there is work to do. */ -void -srv_wake_purge_thread_if_not_active() +void srv_wake_purge_thread_if_not_active() { - ut_ad(!srv_read_only_mode); + ut_ad(!srv_read_only_mode); - if (purge_sys.enabled() && !purge_sys.paused() - && trx_sys.history_exists()) { - if(++purge_state.m_running == 1) { - srv_thread_pool->submit_task(&purge_coordinator_task); - } - } + if (purge_sys.enabled() && !purge_sys.paused() && + (srv_undo_log_truncate || trx_sys.history_exists()) && + ++purge_state.m_running == 1) + srv_thread_pool->submit_task(&purge_coordinator_task); } /** @return whether the purge tasks are active */ @@ -1664,13 +1661,20 @@ fewer_threads: m_history_length= history_size; if (!history_size) + { srv_dml_needed_delay= 0; - else if (trx_purge(n_use_threads, history_size, - !(++count % srv_purge_rseg_truncate_frequency) || - purge_sys.truncate.current || - (srv_shutdown_state != SRV_SHUTDOWN_NONE && - srv_fast_shutdown == 0))) - continue; + trx_purge_truncate_history(); + } + else + { + ulint n_pages_handled= trx_purge(n_use_threads, history_size); + if (!(++count % srv_purge_rseg_truncate_frequency) || + purge_sys.truncate.current || + (srv_shutdown_state != SRV_SHUTDOWN_NONE && srv_fast_shutdown == 0)) + trx_purge_truncate_history(); + if (n_pages_handled) + continue; + } if (srv_dml_needed_delay); else if (m_running == sigcount) diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 3522b2ef008..989cdd61e98 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -560,10 +560,11 @@ __attribute__((optimize(0))) # endif #endif /** -Removes unnecessary history data from rollback segments. NOTE that when this -function is called, the caller must not have any latches on undo log pages! +Remove unnecessary history data from rollback segments. NOTE that when this +function is called, the caller (purge_coordinator_callback) +must not have any latches on undo log pages! */ -TRANSACTIONAL_TARGET static void trx_purge_truncate_history() +TRANSACTIONAL_TARGET void trx_purge_truncate_history() { ut_ad(purge_sys.head <= purge_sys.tail); purge_sys_t::iterator &head= purge_sys.head.trx_no @@ -585,7 +586,7 @@ TRANSACTIONAL_TARGET static void trx_purge_truncate_history() if (dberr_t e= trx_purge_truncate_rseg_history(rseg, head, !rseg.is_referenced() && - rseg.needs_purge <= head.trx_no)) + purge_sys.sees(rseg.needs_purge))) err= e; rseg.latch.wr_unlock(); } @@ -643,7 +644,7 @@ TRANSACTIONAL_TARGET static void trx_purge_truncate_history() rseg.latch.rd_lock(SRW_LOCK_CALL); ut_ad(rseg.skip_allocation()); - if (rseg.is_referenced() || rseg.needs_purge > head.trx_no) + if (rseg.is_referenced() || !purge_sys.sees(rseg.needs_purge)) { not_free: rseg.latch.rd_unlock(); @@ -657,7 +658,7 @@ not_free: for (const trx_undo_t *undo= UT_LIST_GET_FIRST(rseg.undo_cached); undo; undo= UT_LIST_GET_NEXT(undo_list, undo)) { - if (head.trx_no < undo->trx_id) + if (head.trx_no && head.trx_no < undo->trx_id) goto not_free; else cached+= undo->size; @@ -790,7 +791,7 @@ not_free: continue; ut_ad(!rseg.is_referenced()); - ut_ad(rseg.needs_purge <= head.trx_no); + ut_ad(!head.trx_no || rseg.needs_purge <= head.trx_no); buf_block_t *rblock= trx_rseg_header_create(&space, &rseg - trx_sys.rseg_array, @@ -1263,10 +1264,8 @@ TRANSACTIONAL_INLINE void purge_sys_t::clone_end_view() Run a purge batch. @param n_tasks number of purge tasks to submit to the queue @param history_size trx_sys.history_size() -@param truncate whether to truncate the history at the end of the batch @return number of undo log pages handled in the batch */ -TRANSACTIONAL_TARGET -ulint trx_purge(ulint n_tasks, ulint history_size, bool truncate) +TRANSACTIONAL_TARGET ulint trx_purge(ulint n_tasks, ulint history_size) { que_thr_t* thr = NULL; ulint n_pages_handled; @@ -1318,10 +1317,6 @@ ulint trx_purge(ulint n_tasks, ulint history_size, bool truncate) purge_sys.clone_end_view(); - if (truncate) { - trx_purge_truncate_history(); - } - MONITOR_INC_VALUE(MONITOR_PURGE_INVOKED, 1); MONITOR_INC_VALUE(MONITOR_PURGE_N_PAGE_HANDLED, n_pages_handled);