summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2023-01-17 20:02:29 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2023-01-17 20:02:29 +0200
commita8c5635cf156d353c58d940bb5fd3ac026159b95 (patch)
tree2b14ada67f3f08d14f1ae54f7e5c4ad45e63cf10
parent95de5248c7f59f96039f96f5442142c79da27b20 (diff)
parent0459d2ccfc782475e596c9991e0525186953a4f3 (diff)
downloadmariadb-git-a8c5635cf156d353c58d940bb5fd3ac026159b95.tar.gz
Merge 10.5 into 10.6
-rw-r--r--CREDITS2
m---------libmariadb0
-rw-r--r--mysql-test/main/constraints.result34
-rw-r--r--mysql-test/main/constraints.test17
-rw-r--r--mysql-test/main/join.result17
-rw-r--r--mysql-test/main/join.test15
-rw-r--r--mysql-test/suite/federated/federatedx.result32
-rw-r--r--mysql-test/suite/federated/federatedx.test30
-rw-r--r--mysql-test/suite/galera/r/galera_MDEV-29512.result40
-rw-r--r--mysql-test/suite/galera/r/galera_gcache_recover.result2
-rw-r--r--mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result2
-rw-r--r--mysql-test/suite/galera/r/galera_savepoint_replay.result53
-rw-r--r--mysql-test/suite/galera/t/galera_MDEV-29512.cnf15
-rw-r--r--mysql-test/suite/galera/t/galera_MDEV-29512.test91
-rw-r--r--mysql-test/suite/galera/t/galera_gcache_recover.test17
-rw-r--r--mysql-test/suite/galera/t/galera_gcache_recover_manytrx.test16
-rw-r--r--mysql-test/suite/galera/t/galera_savepoint_replay.test86
-rw-r--r--mysql-test/suite/galera_3nodes/r/MDEV-29171.result41
-rw-r--r--mysql-test/suite/galera_3nodes/t/MDEV-29171.cnf14
-rw-r--r--mysql-test/suite/galera_3nodes/t/MDEV-29171.test83
-rw-r--r--mysql-test/suite/galera_3nodes_sr/t/galera_vote_sr.inc2
-rw-r--r--mysql-test/suite/innodb/r/foreign_key.result2
-rw-r--r--mysql-test/suite/innodb/t/foreign_key.test2
-rw-r--r--sql/field.h2
-rw-r--r--sql/handler.h4
-rw-r--r--sql/item.cc2
-rw-r--r--sql/item.h7
-rw-r--r--sql/item_jsonfunc.cc2
-rw-r--r--sql/opt_subselect.cc24
-rw-r--r--sql/service_wsrep.cc17
-rw-r--r--sql/sql_class.cc4
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_select.cc6
-rw-r--r--sql/sql_select.h2
-rw-r--r--sql/sql_table.cc6
-rw-r--r--sql/wsrep_high_priority_service.cc35
-rw-r--r--sql/wsrep_mysqld.cc4
-rw-r--r--sql/wsrep_thd.cc25
-rw-r--r--sql/wsrep_thd.h6
-rw-r--r--storage/innobase/handler/ha_innodb.cc10
-rw-r--r--storage/innobase/lock/lock0lock.cc47
41 files changed, 709 insertions, 109 deletions
diff --git a/CREDITS b/CREDITS
index 35092602ccf..9534d3e6e83 100644
--- a/CREDITS
+++ b/CREDITS
@@ -9,10 +9,8 @@ MariaDB Corporation https://www.mariadb.com (2013)
Microsoft https://microsoft.com/ (2017)
ServiceNow https://servicenow.com (2019)
SIT https://sit.org (2022)
-Tencent Cloud https://cloud.tencent.com (2017)
Development Bank of Singapore https://dbs.com (2016)
IBM https://www.ibm.com (2017)
-Visma https://visma.com (2015)
Automattic https://automattic.com (2019)
Galera Cluster https://galeracluster.com (2020)
Percona https://www.percona.com (2018)
diff --git a/libmariadb b/libmariadb
-Subproject 72b40bfaa869f3fe84242471dda989d13983d84
+Subproject 12bd1d5511fc2ff766ff6256c71b79a95739533
diff --git a/mysql-test/main/constraints.result b/mysql-test/main/constraints.result
index ca4b762fa5c..143c22321ab 100644
--- a/mysql-test/main/constraints.result
+++ b/mysql-test/main/constraints.result
@@ -183,7 +183,9 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
DROP PROCEDURE sp;
DROP TABLE t1;
+#
# End of 10.2 tests
+#
create table t1 (a int check (a>10)) select 100 as 'a';
show create table t1;
Table Create Table
@@ -201,3 +203,35 @@ a
19
ccc
drop table t1;
+create table t1 (a int, b int);
+create procedure sp() alter table t1 add constraint if not exists foo check (b > 0);
+call sp;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ CONSTRAINT `foo` CHECK (`b` > 0)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
+call sp;
+Warnings:
+Note 1826 Duplicate CHECK constraint name 'foo'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ CONSTRAINT `foo` CHECK (`b` > 0)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
+call sp;
+Warnings:
+Note 1826 Duplicate CHECK constraint name 'foo'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ CONSTRAINT `foo` CHECK (`b` > 0)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
+drop procedure sp;
+drop table t1;
diff --git a/mysql-test/main/constraints.test b/mysql-test/main/constraints.test
index 2f4dadcee9d..5c673f9be81 100644
--- a/mysql-test/main/constraints.test
+++ b/mysql-test/main/constraints.test
@@ -151,7 +151,9 @@ show create table t1;
DROP PROCEDURE sp;
DROP TABLE t1;
+--echo #
--echo # End of 10.2 tests
+--echo #
#
# Check that we don't lose constraints as part of CREATE ... SELECT
@@ -172,3 +174,18 @@ insert into t1 values ("ccc");
insert into t1 values ("");
select * from t1;
drop table t1;
+
+#
+# add if not exists in SP
+#
+
+create table t1 (a int, b int);
+create procedure sp() alter table t1 add constraint if not exists foo check (b > 0);
+call sp;
+show create table t1;
+call sp;
+show create table t1;
+call sp;
+show create table t1;
+drop procedure sp;
+drop table t1;
diff --git a/mysql-test/main/join.result b/mysql-test/main/join.result
index 11b7ecad3ee..942ee96fc32 100644
--- a/mysql-test/main/join.result
+++ b/mysql-test/main/join.result
@@ -3407,3 +3407,20 @@ id select_type table type possible_keys key key_len ref rows Extra
drop table t1,t2,t3;
drop table t1000,t10,t03;
# End of 10.3 tests
+#
+# MDEV-30080 Wrong result with LEFT JOINs involving constant tables
+#
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1);
+CREATE TABLE t2 (b INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1),(1);
+CREATE TABLE t3 (c INT PRIMARY KEY) ENGINE=MyISAM;
+SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b = t3.c) ON t1.a = t2.b;
+a b c
+1 1 NULL
+1 1 NULL
+SELECT COUNT(*) FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b = t3.c) ON t1.a = t2.b;
+COUNT(*)
+2
+DROP TABLE t1, t2, t3;
+# End of 10.5 tests
diff --git a/mysql-test/main/join.test b/mysql-test/main/join.test
index b99f05f7c88..c8bd2886b30 100644
--- a/mysql-test/main/join.test
+++ b/mysql-test/main/join.test
@@ -1820,3 +1820,18 @@ drop table t1,t2,t3;
drop table t1000,t10,t03;
--echo # End of 10.3 tests
+
+--echo #
+--echo # MDEV-30080 Wrong result with LEFT JOINs involving constant tables
+--echo #
+
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1);
+CREATE TABLE t2 (b INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1),(1);
+CREATE TABLE t3 (c INT PRIMARY KEY) ENGINE=MyISAM;
+SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b = t3.c) ON t1.a = t2.b;
+SELECT COUNT(*) FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b = t3.c) ON t1.a = t2.b;
+DROP TABLE t1, t2, t3;
+
+--echo # End of 10.5 tests
diff --git a/mysql-test/suite/federated/federatedx.result b/mysql-test/suite/federated/federatedx.result
index c18665e4d99..49deff81c4c 100644
--- a/mysql-test/suite/federated/federatedx.result
+++ b/mysql-test/suite/federated/federatedx.result
@@ -2325,6 +2325,38 @@ DROP TABLE federated.t1;
connection slave;
DROP TABLE federated.t1;
connection default;
+#
+# MDEV-30395 Wrong result with semijoin and Federated as outer table
+#
+create server s foreign data wrapper mysql options (host "127.0.0.1", database "test", user "root", port MASTER_PORT);
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (3),(2),(3);
+CREATE TABLE t2 (pk INT PRIMARY KEY);
+INSERT INTO t2 VALUES (1),(2),(3),(4);
+set @save_optimizer_switch=@@optimizer_switch;
+set optimizer_switch="materialization=off";
+CREATE TABLE t2_fed ENGINE=FEDERATED CONNECTION='s/t2';
+explain SELECT * FROM t2_fed WHERE pk IN ( SELECT a FROM t1 );
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2_fed ALL NULL NULL NULL NULL 4 Using where
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+SELECT * FROM t2_fed WHERE pk IN ( SELECT a FROM t1 );
+pk
+2
+3
+SET optimizer_switch='semijoin=off';
+explain SELECT * FROM t2_fed WHERE pk IN ( SELECT a FROM t1 );
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2_fed ALL NULL NULL NULL NULL 4 Using where
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+SELECT * FROM t2_fed WHERE pk IN ( SELECT a FROM t1 );
+pk
+2
+3
+DROP TABLE t2_fed, t1, t2;
+set @@optimizer_switch=@save_optimizer_switch;
+DROP SERVER s;
+# End of 10.5 tests
connection master;
DROP TABLE IF EXISTS federated.t1;
DROP DATABASE IF EXISTS federated;
diff --git a/mysql-test/suite/federated/federatedx.test b/mysql-test/suite/federated/federatedx.test
index 51d34298626..7e5a335b786 100644
--- a/mysql-test/suite/federated/federatedx.test
+++ b/mysql-test/suite/federated/federatedx.test
@@ -2060,4 +2060,34 @@ connection slave;
DROP TABLE federated.t1;
connection default;
+--echo #
+--echo # MDEV-30395 Wrong result with semijoin and Federated as outer table
+--echo #
+
+
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval create server s foreign data wrapper mysql options (host "127.0.0.1", database "test", user "root", port $MASTER_MYPORT);
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (3),(2),(3);
+CREATE TABLE t2 (pk INT PRIMARY KEY);
+INSERT INTO t2 VALUES (1),(2),(3),(4);
+
+set @save_optimizer_switch=@@optimizer_switch;
+set optimizer_switch="materialization=off";
+
+CREATE TABLE t2_fed ENGINE=FEDERATED CONNECTION='s/t2';
+explain SELECT * FROM t2_fed WHERE pk IN ( SELECT a FROM t1 );
+SELECT * FROM t2_fed WHERE pk IN ( SELECT a FROM t1 );
+SET optimizer_switch='semijoin=off';
+explain SELECT * FROM t2_fed WHERE pk IN ( SELECT a FROM t1 );
+SELECT * FROM t2_fed WHERE pk IN ( SELECT a FROM t1 );
+
+DROP TABLE t2_fed, t1, t2;
+set @@optimizer_switch=@save_optimizer_switch;
+
+DROP SERVER s;
+
+--echo # End of 10.5 tests
+
source include/federated_cleanup.inc;
diff --git a/mysql-test/suite/galera/r/galera_MDEV-29512.result b/mysql-test/suite/galera/r/galera_MDEV-29512.result
new file mode 100644
index 00000000000..aaf24df920e
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_MDEV-29512.result
@@ -0,0 +1,40 @@
+connection node_2;
+connection node_1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 int, f3 varchar(2000));
+INSERT INTO t1 VALUES (1, 0, REPEAT('1234567890', 200));
+INSERT INTO t1 VALUES (3, 3, REPEAT('1234567890', 200));
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_apply_cb";
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+connection node_1a;
+SET SESSION wsrep_sync_wait=0;
+connection node_1;
+begin;
+select f1,f2 from t1;
+f1 f2
+1 0
+3 3
+connection node_2;
+UPDATE t1 SET f2=2 WHERE f1=3;
+connection node_1a;
+SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached";
+connection node_1;
+UPDATE t1 SET f2=1 WHERE f1=3;
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+COMMIT;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+SET GLOBAL DEBUG_DBUG = "";
+SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
+SET GLOBAL debug_dbug = NULL;
+SET debug_sync='RESET';
+connection node_1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select f1,f2 from t1;
+f1 f2
+1 0
+3 2
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_gcache_recover.result b/mysql-test/suite/galera/r/galera_gcache_recover.result
index 819c595ece3..72088a5447b 100644
--- a/mysql-test/suite/galera/r/galera_gcache_recover.result
+++ b/mysql-test/suite/galera/r/galera_gcache_recover.result
@@ -20,8 +20,6 @@ connection node_1;
include/diff_servers.inc [servers=1 2]
connection node_1;
CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
-include/assert_grep.inc [async IST sender starting to serve]
connection node_2;
CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
-include/assert_grep.inc [Recovering GCache ring buffer: found gapless sequence]
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result b/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result
index 63b16165970..5caf22b39ca 100644
--- a/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result
+++ b/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result
@@ -134,8 +134,6 @@ connection node_1;
call mtr.add_suppression("Error in Log_event::read_log_event():.*");
CALL mtr.add_suppression("conflict state 7 after post commit");
CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
-include/assert_grep.inc [async IST sender starting to serve]
connection node_2;
call mtr.add_suppression("Error in Log_event::read_log_event():.*");
CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
-include/assert_grep.inc [Recovering GCache ring buffer: found gapless sequence]
diff --git a/mysql-test/suite/galera/r/galera_savepoint_replay.result b/mysql-test/suite/galera/r/galera_savepoint_replay.result
new file mode 100644
index 00000000000..afea5f82e3c
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_savepoint_replay.result
@@ -0,0 +1,53 @@
+connection node_2;
+connection node_1;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+connection node_1;
+SET AUTOCOMMIT=ON;
+START TRANSACTION;
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
+f1 f2
+2 a
+SAVEPOINT my_sp;
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+SET SESSION wsrep_sync_wait=0;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
+connection node_1;
+COMMIT;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'signal=abort_trx_end';
+SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_master_enter_sync';
+connection node_1;
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 1
+1
+wsrep_local_replays
+1
+connection node_2;
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+COUNT(*) = 1
+1
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+COUNT(*) = 1
+1
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/galera_MDEV-29512.cnf b/mysql-test/suite/galera/t/galera_MDEV-29512.cnf
new file mode 100644
index 00000000000..bf8e0c37984
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_MDEV-29512.cnf
@@ -0,0 +1,15 @@
+!include ../galera_2nodes.cnf
+
+[mysqld]
+log-bin
+log-slave-updates
+
+[mysqld.1]
+log_bin
+log_slave_updates
+max-binlog-size=4096
+expire-logs-days=1
+
+
+[mysqld.2]
+
diff --git a/mysql-test/suite/galera/t/galera_MDEV-29512.test b/mysql-test/suite/galera/t/galera_MDEV-29512.test
new file mode 100644
index 00000000000..ffcef792f85
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_MDEV-29512.test
@@ -0,0 +1,91 @@
+#
+# This test is for reproducing the issue in:
+# https://jira.mariadb.org/browse/MDEV-29512
+#
+# The hanging in MDEV-29512 happens when binlog purging is attempted, and there is
+# one local BF aborted transaction waiting for commit monitor.
+#
+# The test will launch two node cluster and enable binlogging with expire log days,
+# to force binlog purging to happen.
+# A local transaction is executed so that will become BF abort victim, and has advanced
+# to replication stage waiting for commit monitor for final cleanup (to mark position in innodb)
+# after that, applier is released to complete the BF abort and due to binlog configuration,
+# starting the binlog purging. This is where the hanging would occur, if code is buggy
+#
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
+
+#
+# binlog size is limited to 4096 bytes, we will create enough events to
+# cause binlog rotation
+#
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 int, f3 varchar(2000));
+INSERT INTO t1 VALUES (1, 0, REPEAT('1234567890', 200));
+INSERT INTO t1 VALUES (3, 3, REPEAT('1234567890', 200));
+
+SET SESSION wsrep_sync_wait=0;
+
+# set sync point for replication applier
+SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_apply_cb";
+
+# Control connection to manage sync points for appliers
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION wsrep_sync_wait=0;
+
+# starting local transaction, only select so far,
+# write will happen later and this will be ordered after the transaction in node_2
+--connection node_1
+begin;
+select f1,f2 from t1;
+
+# send from node 2 an UPDATE transaction, which will BF abort the transaction in node_1
+--connection node_2
+--let $wait_condition=select count(*)=2 from t1
+--source include/wait_condition.inc
+
+UPDATE t1 SET f2=2 WHERE f1=3;
+
+--connection node_1a
+# wait to see the UPDATE from node_2 in apply_cb sync point
+SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached";
+
+--connection node_1
+# now issuing conflicting update
+UPDATE t1 SET f2=1 WHERE f1=3;
+
+# Block the local commit, send final COMMIT and wait until it gets blocked
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_set_sync_point.inc
+--send COMMIT
+
+--connection node_1a
+# wait for the local commit to enter in commit monitor wait state
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+# release the local transaction to continue with commit
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_signal_sync_point.inc
+
+# and now release the applier, it should force local trx to abort
+SET GLOBAL DEBUG_DBUG = "";
+SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
+SET GLOBAL debug_dbug = NULL;
+SET debug_sync='RESET';
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+--reap
+
+# wait until applying is complete
+--let $wait_condition = SELECT COUNT(*)=1 FROM t1 WHERE f2=2
+--source include/wait_condition.inc
+
+# final read to verify what we got
+select f1,f2 from t1;
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/galera_gcache_recover.test b/mysql-test/suite/galera/t/galera_gcache_recover.test
index e1bfe517d27..fe2a65ee14e 100644
--- a/mysql-test/suite/galera/t/galera_gcache_recover.test
+++ b/mysql-test/suite/galera/t/galera_gcache_recover.test
@@ -54,24 +54,7 @@ INSERT INTO t1 VALUES (3);
# Warning happens when the cluster is started for the first time
CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
-# Confirm that IST took place
---let $assert_text = async IST sender starting to serve
---let $assert_select = async IST sender starting to serve
---let $assert_count = 1
---let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err
---let $assert_only_after = starting as process
---source include/assert_grep.inc
-
--connection node_2
CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
-# Confirm that gcache recovery took place
-
---let $assert_text = Recovering GCache ring buffer: found gapless sequence
---let $assert_select = Recovering GCache ring buffer: found gapless sequence
---let $assert_count = 1
---let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err
---let $assert_only_after = starting as process
---source include/assert_grep.inc
-
DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/galera_gcache_recover_manytrx.test b/mysql-test/suite/galera/t/galera_gcache_recover_manytrx.test
index d92288b7881..8f0f0ed65ea 100644
--- a/mysql-test/suite/galera/t/galera_gcache_recover_manytrx.test
+++ b/mysql-test/suite/galera/t/galera_gcache_recover_manytrx.test
@@ -206,23 +206,7 @@ CALL mtr.add_suppression("conflict state 7 after post commit");
# Warning happens when the cluster is started for the first time
CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
-# Confirm that IST took place
---let $assert_text = async IST sender starting to serve
---let $assert_select = async IST sender starting to serve
---let $assert_count = 1
---let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err
---let $assert_only_after = starting as process
---source include/assert_grep.inc
-
--connection node_2
call mtr.add_suppression("Error in Log_event::read_log_event():.*");
CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
-# Confirm that gcache recovery took place
-
---let $assert_text = Recovering GCache ring buffer: found gapless sequence
---let $assert_select = Recovering GCache ring buffer: found gapless sequence
---let $assert_count = 1
---let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err
---let $assert_only_after = starting as process
---source include/assert_grep.inc
diff --git a/mysql-test/suite/galera/t/galera_savepoint_replay.test b/mysql-test/suite/galera/t/galera_savepoint_replay.test
new file mode 100644
index 00000000000..cff26f4a94f
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_savepoint_replay.test
@@ -0,0 +1,86 @@
+#
+# This test tests replaying a transaction with savepoint
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
+
+--let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1));
+INSERT INTO t1 VALUES (1, 'a');
+INSERT INTO t1 VALUES (2, 'a');
+
+--connection node_1
+SET AUTOCOMMIT=ON;
+START TRANSACTION;
+
+UPDATE t1 SET f2 = 'b' WHERE f1 = 1;
+SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE;
+SAVEPOINT my_sp;
+
+# Block the applier on node #1 and issue a conflicting update on node #2
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+SET SESSION wsrep_sync_wait=0;
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_set_sync_point.inc
+
+--connection node_2
+UPDATE t1 SET f2 = 'c' WHERE f1 = 2;
+
+--connection node_1a
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+# Block the commit, send the COMMIT and wait until it gets blocked
+
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_set_sync_point.inc
+
+--connection node_1
+--send COMMIT
+
+--connection node_1a
+
+--let $galera_sync_point = apply_monitor_slave_enter_sync commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+
+# Let the conflicting UPDATE proceed and wait until it hits abort_trx_end.
+# The victim transaction still sits in commit_monitor_master_sync_point.
+
+--let $galera_sync_point = abort_trx_end
+--source include/galera_set_sync_point.inc
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = abort_trx_end commit_monitor_master_enter_sync
+--source include/galera_wait_sync_point.inc
+
+# Let the transactions proceed
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = abort_trx_end
+--source include/galera_signal_sync_point.inc
+--let $galera_sync_point = commit_monitor_master_enter_sync
+--source include/galera_signal_sync_point.inc
+
+# Commit succeeds
+--connection node_1
+--reap
+
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+
+# wsrep_local_replays has increased by 1
+--let $wsrep_local_replays_new = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'`
+--disable_query_log
+--eval SELECT $wsrep_local_replays_new - $wsrep_local_replays_old = 1 AS wsrep_local_replays;
+--enable_query_log
+
+--connection node_2
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'b';
+SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c';
+
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/galera_3nodes/r/MDEV-29171.result b/mysql-test/suite/galera_3nodes/r/MDEV-29171.result
new file mode 100644
index 00000000000..151be86d9cc
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes/r/MDEV-29171.result
@@ -0,0 +1,41 @@
+connection node_2;
+connection node_1;
+connection node_1;
+select @@wsrep_gtid_domain_id,@@wsrep_node_name;
+@@wsrep_gtid_domain_id @@wsrep_node_name
+100 node1
+connection node_2;
+select @@wsrep_gtid_domain_id,@@wsrep_node_name;
+@@wsrep_gtid_domain_id @@wsrep_node_name
+100 node2
+connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
+connection node_3;
+select @@wsrep_gtid_domain_id,@@wsrep_node_name;
+@@wsrep_gtid_domain_id @@wsrep_node_name
+100 node3
+connection node_3;
+connection node_2;
+connection node_1;
+connection node_1;
+# restart: --wsrep_new_cluster --wsrep_gtid_domain_id=200
+show variables like 'wsrep_gtid_domain_id';
+Variable_name Value
+wsrep_gtid_domain_id 200
+connection node_2;
+# restart
+show variables like 'wsrep_gtid_domain_id';
+Variable_name Value
+wsrep_gtid_domain_id 200
+connection node_3;
+# restart: --wsrep_sst_donor=node2
+show variables like 'wsrep_gtid_domain_id';
+Variable_name Value
+wsrep_gtid_domain_id 200
+connection node_1;
+set global wsrep_gtid_domain_id=100;
+connection node_2;
+set global wsrep_gtid_domain_id=100;
+CALL mtr.add_suppression("WSREP: Ignoring server id for non bootstrap node.");
+connection node_3;
+set global wsrep_gtid_domain_id=100;
+CALL mtr.add_suppression("WSREP: Ignoring server id for non bootstrap node.");
diff --git a/mysql-test/suite/galera_3nodes/t/MDEV-29171.cnf b/mysql-test/suite/galera_3nodes/t/MDEV-29171.cnf
new file mode 100644
index 00000000000..27f1c29f999
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes/t/MDEV-29171.cnf
@@ -0,0 +1,14 @@
+!include ../galera_3nodes.cnf
+
+[mysqld.1]
+wsrep-node-name="node1"
+wsrep-gtid-mode=ON
+wsrep-gtid-domain-id=100
+
+[mysqld.2]
+wsrep-node-name="node2"
+wsrep-gtid-mode=ON
+
+[mysqld.3]
+wsrep-node-name="node3"
+wsrep-gtid-mode=ON
diff --git a/mysql-test/suite/galera_3nodes/t/MDEV-29171.test b/mysql-test/suite/galera_3nodes/t/MDEV-29171.test
new file mode 100644
index 00000000000..33fa4d722ae
--- /dev/null
+++ b/mysql-test/suite/galera_3nodes/t/MDEV-29171.test
@@ -0,0 +1,83 @@
+#
+# MDEV-29171: changing the value of wsrep_gtid_domain_id
+# with full cluster restart fails on some nodes
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+
+#
+# Initially wsrep gtid domain id is 100
+#
+--connection node_1
+select @@wsrep_gtid_domain_id,@@wsrep_node_name;
+
+--connection node_2
+select @@wsrep_gtid_domain_id,@@wsrep_node_name;
+
+--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
+--connection node_3
+select @@wsrep_gtid_domain_id,@@wsrep_node_name;
+
+
+#
+# Shutdown all nodes
+#
+--connection node_3
+--source include/shutdown_mysqld.inc
+
+--connection node_2
+--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+--source include/shutdown_mysqld.inc
+
+--connection node_1
+--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
+--source include/wait_condition.inc
+--source include/shutdown_mysqld.inc
+
+
+#
+# Bootstrap from node_1 and change wsrep_gtid_domain_id to 200
+#
+--connection node_1
+--let $restart_parameters = --wsrep_new_cluster --wsrep_gtid_domain_id=200
+--source include/start_mysqld.inc
+show variables like 'wsrep_gtid_domain_id';
+
+
+#
+# Restart node_2, expect that wsrep_gtid_domain_id has changed to 200
+#
+--connection node_2
+--let $restart_parameters =
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+--source include/start_mysqld.inc
+show variables like 'wsrep_gtid_domain_id';
+
+
+#
+# Restart node_3, select node_2 as donor
+# If bug is present, node_3 remains on domain id 100
+#
+--connection node_3
+--let $restart_parameters = --wsrep_sst_donor="node2"
+--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.3.expect
+--source include/start_mysqld.inc
+# Expect domain id 200
+show variables like 'wsrep_gtid_domain_id';
+
+
+#
+# Cleanup
+#
+--connection node_1
+set global wsrep_gtid_domain_id=100;
+
+--connection node_2
+set global wsrep_gtid_domain_id=100;
+CALL mtr.add_suppression("WSREP: Ignoring server id for non bootstrap node.");
+
+--connection node_3
+set global wsrep_gtid_domain_id=100;
+CALL mtr.add_suppression("WSREP: Ignoring server id for non bootstrap node.");
diff --git a/mysql-test/suite/galera_3nodes_sr/t/galera_vote_sr.inc b/mysql-test/suite/galera_3nodes_sr/t/galera_vote_sr.inc
index 776291cc9c0..9fe33e78eb5 100644
--- a/mysql-test/suite/galera_3nodes_sr/t/galera_vote_sr.inc
+++ b/mysql-test/suite/galera_3nodes_sr/t/galera_vote_sr.inc
@@ -8,6 +8,8 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 BLOB) ENGINE=InnoDB;
# Introduce inconsistency
--connection node_2
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'
+--source include/wait_condition.inc
SET SESSION wsrep_on=OFF;
--eval INSERT INTO t1 VALUES ($inconsistent_fragment, 'X')
SET SESSION wsrep_on=ON;
diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result
index 0b85048b650..acf021db22c 100644
--- a/mysql-test/suite/innodb/r/foreign_key.result
+++ b/mysql-test/suite/innodb/r/foreign_key.result
@@ -944,6 +944,8 @@ DROP TABLE t1;
#
# TODO: enable them after MDEV-16417 is finished
create or replace table t1 (a int primary key) engine=innodb;
+create or replace table t2 (a int, constraint foo check(a > 0), foreign key(a) references t1(a) on update cascade) engine=innodb;
+ERROR HY000: Function or expression 'a' cannot be used in the CHECK clause of `foo`
create or replace table t2 (a int, check(a > 0), foreign key(a) references t1(a) on update cascade) engine=innodb;
ERROR HY000: Function or expression 'a' cannot be used in the CHECK clause of `CONSTRAINT_1`
create or replace table t1 (f1 int, f2 date, f3 date, key(f1,f3,f2)) engine=innodb;
diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test
index 918d8e8df20..4b047ea4d4a 100644
--- a/mysql-test/suite/innodb/t/foreign_key.test
+++ b/mysql-test/suite/innodb/t/foreign_key.test
@@ -970,6 +970,8 @@ DROP TABLE t1;
--echo # TODO: enable them after MDEV-16417 is finished
create or replace table t1 (a int primary key) engine=innodb;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create or replace table t2 (a int, constraint foo check(a > 0), foreign key(a) references t1(a) on update cascade) engine=innodb;
+--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
create or replace table t2 (a int, check(a > 0), foreign key(a) references t1(a) on update cascade) engine=innodb;
create or replace table t1 (f1 int, f2 date, f3 date, key(f1,f3,f2)) engine=innodb;
diff --git a/sql/field.h b/sql/field.h
index 62dbdc00176..12d822207ec 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -558,7 +558,6 @@ static inline const char *vcol_type_name(enum_vcol_info_type type)
#define VCOL_AUTO_INC 16
#define VCOL_IMPOSSIBLE 32
#define VCOL_NEXTVAL 64 /* NEXTVAL is not implemented for vcols */
-#define VCOL_CHECK_CONSTRAINT_IF_NOT_EXISTS 128
#define VCOL_NOT_STRICTLY_DETERMINISTIC \
(VCOL_NON_DETERMINISTIC | VCOL_TIME_FUNC | VCOL_SESSION_FUNC)
@@ -590,6 +589,7 @@ public:
bool stored_in_db;
bool utf8; /* Already in utf8 */
bool automatic_name;
+ bool if_not_exists;
Item *expr;
Lex_ident name; /* Name of constraint */
/* see VCOL_* (VCOL_FIELD_REF, ...) */
diff --git a/sql/handler.h b/sql/handler.h
index de08e2c2137..f4d94924bda 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -357,9 +357,9 @@ enum chf_create_flags {
Rowid's are not comparable. This is set if the rowid is unique to the
current open handler, like it is with federated where the rowid is a
pointer to a local result set buffer. The effect of having this set is
- that the optimizer will not consirer the following optimizations for
+ that the optimizer will not consider the following optimizations for
the table:
- ror scans or filtering
+ ror scans, filtering or duplicate weedout
*/
#define HA_NON_COMPARABLE_ROWID (1ULL << 60)
diff --git a/sql/item.cc b/sql/item.cc
index 4f5b207c9e5..0b72b52eb69 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -3476,7 +3476,7 @@ bool Item_field::is_null_result()
bool Item_field::eq(const Item *item, bool binary_cmp) const
{
- Item *real_item2= ((Item *) item)->real_item();
+ const Item *real_item2= item->real_item();
if (real_item2->type() != FIELD_ITEM)
return 0;
diff --git a/sql/item.h b/sql/item.h
index 18a3c1340c0..04b7b33904b 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2093,6 +2093,7 @@ public:
virtual Item *copy_or_same(THD *thd) { return this; }
virtual Item *copy_andor_structure(THD *thd) { return this; }
virtual Item *real_item() { return this; }
+ const Item *real_item() const { return const_cast<Item*>(this)->real_item(); }
virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); }
virtual Item *make_odbc_literal(THD *thd, const LEX_CSTRING *typestr)
{
@@ -5577,7 +5578,7 @@ public:
{ return ref ? (*ref)->type() : REF_ITEM; }
bool eq(const Item *item, bool binary_cmp) const override
{
- Item *it= ((Item *) item)->real_item();
+ const Item *it= item->real_item();
return ref && (*ref)->eq(it, binary_cmp);
}
void save_val(Field *to) override;
@@ -5933,7 +5934,7 @@ public:
{ orig_item->make_send_field(thd, field); }
bool eq(const Item *item, bool binary_cmp) const override
{
- Item *it= const_cast<Item*>(item)->real_item();
+ const Item *it= item->real_item();
return orig_item->eq(it, binary_cmp);
}
void fix_after_pullout(st_select_lex *new_parent, Item **refptr, bool merge)
@@ -7806,7 +7807,7 @@ public:
{ m_item->make_send_field(thd, field); }
bool eq(const Item *item, bool binary_cmp) const
{
- Item *it= ((Item *) item)->real_item();
+ const Item *it= item->real_item();
return m_item->eq(it, binary_cmp);
}
void fix_after_pullout(st_select_lex *new_parent, Item **refptr, bool merge)
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index bbfd5f012eb..2ed387ac8cc 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -1628,7 +1628,7 @@ bool is_json_type(const Item *item)
if (Type_handler_json_common::is_json_type_handler(item->type_handler()))
return true;
const Item_func_conv_charset *func;
- if (!(func= dynamic_cast<const Item_func_conv_charset*>(item)))
+ if (!(func= dynamic_cast<const Item_func_conv_charset*>(item->real_item())))
return false;
item= func->arguments()[0];
}
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index b971c96cda2..aa61d2c4605 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -664,6 +664,17 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
DBUG_RETURN(-1);
}
}
+ /* Check if any table is not supporting comparable rowids */
+ {
+ List_iterator_fast<TABLE_LIST> li(select_lex->outer_select()->leaf_tables);
+ TABLE_LIST *tbl;
+ while ((tbl = li++))
+ {
+ TABLE *table= tbl->table;
+ if (table && table->file->ha_table_flags() & HA_NON_COMPARABLE_ROWID)
+ join->not_usable_rowid_map|= table->map;
+ }
+ }
DBUG_PRINT("info", ("Checking if subq can be converted to semi-join"));
/*
@@ -683,8 +694,11 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
9. Parent select is not a table-less select
10. Neither parent nor child select have STRAIGHT_JOIN option.
11. It is first optimisation (the subquery could be moved from ON
- clause during first optimisation and then be considered for SJ
- on the second when it is too late)
+ clause during first optimisation and then be considered for SJ
+ on the second when it is too late)
+ 12. All tables supports comparable rowids.
+ This is needed for DuplicateWeedout strategy to work (which
+ is the catch-all semi-join strategy so it must be applicable).
*/
if (optimizer_flag(thd, OPTIMIZER_SWITCH_SEMIJOIN) &&
in_subs && // 1
@@ -699,7 +713,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
!((join->select_options | // 10
select_lex->outer_select()->join->select_options) // 10
& SELECT_STRAIGHT_JOIN) && // 10
- select_lex->first_cond_optimization) // 11
+ select_lex->first_cond_optimization && // 11
+ join->not_usable_rowid_map == 0) // 12
{
DBUG_PRINT("info", ("Subquery is semi-join conversion candidate"));
@@ -3556,6 +3571,9 @@ bool Duplicate_weedout_picker::check_qep(JOIN *join,
}
else
{
+ /* Ensure that table supports comparable rowids */
+ DBUG_ASSERT(!(p->table->table->file->ha_table_flags() & HA_NON_COMPARABLE_ROWID));
+
sj_outer_fanout= COST_MULT(sj_outer_fanout, p->records_read);
temptable_rec_size += p->table->table->file->ref_length;
}
diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc
index f0f9530c80d..943db803242 100644
--- a/sql/service_wsrep.cc
+++ b/sql/service_wsrep.cc
@@ -1,4 +1,4 @@
-/* Copyright 2018 Codership Oy <info@codership.com>
+/* Copyright 2018-2023 Codership Oy <info@codership.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -253,7 +253,9 @@ extern "C" my_bool wsrep_thd_skip_locking(const THD *thd)
extern "C" my_bool wsrep_thd_order_before(const THD *left, const THD *right)
{
- if (wsrep_thd_trx_seqno(left) < wsrep_thd_trx_seqno(right)) {
+ if (wsrep_thd_is_BF(left, false) &&
+ wsrep_thd_is_BF(right, false) &&
+ wsrep_thd_trx_seqno(left) < wsrep_thd_trx_seqno(right)) {
WSREP_DEBUG("BF conflict, order: %lld %lld\n",
(long long)wsrep_thd_trx_seqno(left),
(long long)wsrep_thd_trx_seqno(right));
@@ -368,13 +370,20 @@ extern "C" ulong wsrep_OSU_method_get(const MYSQL_THD thd)
extern "C" bool wsrep_thd_set_wsrep_aborter(THD *bf_thd, THD *victim_thd)
{
- WSREP_DEBUG("wsrep_thd_set_wsrep_aborter called");
mysql_mutex_assert_owner(&victim_thd->LOCK_thd_data);
+ if (!bf_thd)
+ {
+ victim_thd->wsrep_aborter= 0;
+ WSREP_DEBUG("wsrep_thd_set_wsrep_aborter resetting wsrep_aborter");
+ return false;
+ }
if (victim_thd->wsrep_aborter && victim_thd->wsrep_aborter != bf_thd->thread_id)
{
return true;
}
- victim_thd->wsrep_aborter = bf_thd->thread_id;
+ victim_thd->wsrep_aborter= bf_thd->thread_id;
+ WSREP_DEBUG("wsrep_thd_set_wsrep_aborter setting wsrep_aborter %u",
+ victim_thd->wsrep_aborter);
return false;
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 6276b00b939..245bc65ebc8 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -5464,8 +5464,8 @@ thd_need_ordering_with(const MYSQL_THD thd, const MYSQL_THD other_thd)
the caller should guarantee that the BF state won't change.
(e.g. InnoDB does it by keeping lock_sys.mutex locked)
*/
- if (WSREP_ON && wsrep_thd_is_BF(thd, false) &&
- wsrep_thd_is_BF(other_thd, false))
+ if (WSREP_ON &&
+ wsrep_thd_order_before(thd, other_thd))
return 0;
#endif /* WITH_WSREP */
rgi= thd->rgi_slave;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 82453ad8259..51a33af61fc 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -4402,7 +4402,7 @@ public:
bool if_not_exists)
{
constr->name= name;
- constr->flags= if_not_exists ? VCOL_CHECK_CONSTRAINT_IF_NOT_EXISTS : 0;
+ constr->if_not_exists= if_not_exists;
alter_info.check_constraint_list.push_back(constr);
return false;
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 3c2be0b1c8b..75bf4f5197f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -409,7 +409,7 @@ void JOIN::init(THD *thd_arg, List<Item> &fields_arg,
table_count= 0;
top_join_tab_count= 0;
const_tables= 0;
- const_table_map= found_const_table_map= 0;
+ const_table_map= found_const_table_map= not_usable_rowid_map= 0;
aggr_tables= 0;
eliminated_tables= 0;
join_list= 0;
@@ -2476,7 +2476,7 @@ JOIN::optimize_inner()
/*
We have to remove constants and duplicates from group_list before
calling make_join_statistics() as this may call get_best_group_min_max()
- which needs a simplfied group_list.
+ which needs a simplified group_list.
*/
if (group_list && table_count == 1)
{
@@ -5864,7 +5864,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
caller to abort with a zero row result.
*/
TABLE_LIST *emb= s->table->pos_in_table_list->embedding;
- if (emb && !emb->sj_on_expr)
+ if (emb && !emb->sj_on_expr && !*s->on_expr_ref)
{
/* Mark all tables in a multi-table join nest as const */
mark_join_nest_as_const(join, emb, &found_const_table_map,
diff --git a/sql/sql_select.h b/sql/sql_select.h
index ba38cdade55..15d841dfd6a 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1254,6 +1254,8 @@ public:
table_map outer_join;
/* Bitmap of tables used in the select list items */
table_map select_list_used_tables;
+ /* Tables that has HA_NON_COMPARABLE_ROWID (does not support rowid) set */
+ table_map not_usable_rowid_map;
ha_rows send_records,found_records,join_examined_rows, accepted_rows;
/*
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index a951b5d6abb..666f79550c7 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -3640,7 +3640,7 @@ without_overlaps_err:
my_error(ER_TOO_LONG_IDENT, MYF(0), check->name.str);
DBUG_RETURN(TRUE);
}
- if (check_expression(check, &check->name, VCOL_CHECK_TABLE))
+ if (check_expression(check, &check->name, VCOL_CHECK_TABLE, alter_info))
DBUG_RETURN(TRUE);
}
}
@@ -6087,10 +6087,8 @@ remove_key:
while ((check=it++))
{
- if (!(check->flags & VCOL_CHECK_CONSTRAINT_IF_NOT_EXISTS) &&
- check->name.length)
+ if (!check->if_not_exists && check->name.length)
continue;
- check->flags= 0;
for (c= share->field_check_constraints;
c < share->table_check_constraints ; c++)
{
diff --git a/sql/wsrep_high_priority_service.cc b/sql/wsrep_high_priority_service.cc
index 708eb552866..93d4738212d 100644
--- a/sql/wsrep_high_priority_service.cc
+++ b/sql/wsrep_high_priority_service.cc
@@ -1,4 +1,4 @@
-/* Copyright 2018-2021 Codership Oy <info@codership.com>
+/* Copyright 2018-2023 Codership Oy <info@codership.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -639,6 +639,9 @@ Wsrep_replayer_service::Wsrep_replayer_service(THD* replayer_thd, THD* orig_thd)
transactional locks */
DBUG_ASSERT(!orig_thd->mdl_context.has_transactional_locks());
+ replayer_thd->system_thread_info.rpl_sql_info=
+ new rpl_sql_thread_info(replayer_thd->wsrep_rgi->rli->mi->rpl_filter);
+
/* Make a shadow copy of diagnostics area and reset */
m_da_shadow.status= orig_thd->get_stmt_da()->status();
if (m_da_shadow.status == Diagnostics_area::DA_OK)
@@ -677,35 +680,35 @@ Wsrep_replayer_service::Wsrep_replayer_service(THD* replayer_thd, THD* orig_thd)
Wsrep_replayer_service::~Wsrep_replayer_service()
{
- THD* replayer_thd= m_thd;
- THD* orig_thd= m_orig_thd;
-
/* Switch execution context back to original. */
- wsrep_after_apply(replayer_thd);
- wsrep_after_command_ignore_result(replayer_thd);
- wsrep_close(replayer_thd);
- wsrep_reset_threadvars(replayer_thd);
- wsrep_store_threadvars(orig_thd);
+ wsrep_after_apply(m_thd);
+ wsrep_after_command_ignore_result(m_thd);
+ wsrep_close(m_thd);
+ wsrep_reset_threadvars(m_thd);
+ wsrep_store_threadvars(m_orig_thd);
- DBUG_ASSERT(!orig_thd->get_stmt_da()->is_sent());
- DBUG_ASSERT(!orig_thd->get_stmt_da()->is_set());
+ DBUG_ASSERT(!m_orig_thd->get_stmt_da()->is_sent());
+ DBUG_ASSERT(!m_orig_thd->get_stmt_da()->is_set());
+
+ delete m_thd->system_thread_info.rpl_sql_info;
+ m_thd->system_thread_info.rpl_sql_info= nullptr;
if (m_replay_status == wsrep::provider::success)
{
- DBUG_ASSERT(replayer_thd->wsrep_cs().current_error() == wsrep::e_success);
- orig_thd->reset_kill_query();
- my_ok(orig_thd, m_da_shadow.affected_rows, m_da_shadow.last_insert_id);
+ DBUG_ASSERT(m_thd->wsrep_cs().current_error() == wsrep::e_success);
+ m_orig_thd->reset_kill_query();
+ my_ok(m_orig_thd, m_da_shadow.affected_rows, m_da_shadow.last_insert_id);
}
else if (m_replay_status == wsrep::provider::error_certification_failed)
{
- wsrep_override_error(orig_thd, ER_LOCK_DEADLOCK);
+ wsrep_override_error(m_orig_thd, ER_LOCK_DEADLOCK);
}
else
{
DBUG_ASSERT(0);
WSREP_ERROR("trx_replay failed for: %d, schema: %s, query: %s",
m_replay_status,
- orig_thd->db.str, wsrep_thd_query(orig_thd));
+ m_orig_thd->db.str, wsrep_thd_query(m_orig_thd));
unireg_abort(1);
}
}
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index b5c5e98d0d8..7917b2425cb 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -366,10 +366,12 @@ static void wsrep_log_cb(wsrep::log::level level,
void wsrep_init_gtid()
{
wsrep_server_gtid_t stored_gtid= wsrep_get_SE_checkpoint<wsrep_server_gtid_t>();
+ // Domain id may have changed, use the one
+ // received during state transfer.
+ stored_gtid.domain_id= wsrep_gtid_server.domain_id;
if (stored_gtid.server_id == 0)
{
rpl_gtid wsrep_last_gtid;
- stored_gtid.domain_id= wsrep_gtid_server.domain_id;
if (mysql_bin_log.is_open() &&
mysql_bin_log.lookup_domain_in_binlog_state(stored_gtid.domain_id,
&wsrep_last_gtid))
diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc
index 65b537d8b84..420a25dd2ae 100644
--- a/sql/wsrep_thd.cc
+++ b/sql/wsrep_thd.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013-2022 Codership Oy <info@codership.com>
+/* Copyright (C) 2013-2023 Codership Oy <info@codership.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -308,32 +308,37 @@ void wsrep_fire_rollbacker(THD *thd)
}
-int wsrep_abort_thd(THD *bf_thd_ptr, THD *victim_thd_ptr, my_bool signal)
+int wsrep_abort_thd(THD *bf_thd,
+ THD *victim_thd,
+ my_bool signal)
{
DBUG_ENTER("wsrep_abort_thd");
- THD *victim_thd= (THD *) victim_thd_ptr;
- THD *bf_thd= (THD *) bf_thd_ptr;
mysql_mutex_lock(&victim_thd->LOCK_thd_data);
/* Note that when you use RSU node is desynced from cluster, thus WSREP(thd)
might not be true.
*/
- if ((WSREP(bf_thd) ||
+ if ((WSREP_NNULL(bf_thd) ||
((WSREP_ON || bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU) &&
wsrep_thd_is_toi(bf_thd))) &&
- victim_thd &&
!wsrep_thd_is_aborting(victim_thd))
{
- WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu", (bf_thd) ?
- (long long)bf_thd->real_id : 0, (long long)victim_thd->real_id);
+ WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu",
+ (long long)bf_thd->real_id, (long long)victim_thd->real_id);
mysql_mutex_unlock(&victim_thd->LOCK_thd_data);
ha_abort_transaction(bf_thd, victim_thd, signal);
- mysql_mutex_lock(&victim_thd->LOCK_thd_data);
+ DBUG_RETURN(1);
}
else
{
- WSREP_DEBUG("wsrep_abort_thd not effective: %p %p", bf_thd, victim_thd);
+ WSREP_DEBUG("wsrep_abort_thd not effective: bf %llu victim %llu "
+ "wsrep %d wsrep_on %d RSU %d TOI %d aborting %d",
+ (long long)bf_thd->real_id, (long long)victim_thd->real_id,
+ WSREP_NNULL(bf_thd), WSREP_ON,
+ bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU,
+ wsrep_thd_is_toi(bf_thd),
+ wsrep_thd_is_aborting(victim_thd));
}
mysql_mutex_unlock(&victim_thd->LOCK_thd_data);
diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h
index fd48df1494f..3d1bf3733a8 100644
--- a/sql/wsrep_thd.h
+++ b/sql/wsrep_thd.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013-2022 Codership Oy <info@codership.com>
+/* Copyright (C) 2013-2023 Codership Oy <info@codership.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -88,7 +88,9 @@ bool wsrep_create_appliers(long threads, bool mutex_protected=false);
void wsrep_create_rollbacker();
bool wsrep_bf_abort(THD* bf_thd, THD* victim_thd);
-int wsrep_abort_thd(THD *bf_thd_ptr, THD *victim_thd_ptr, my_bool signal);
+int wsrep_abort_thd(THD *bf_thd,
+ THD *victim_thd,
+ my_bool signal) __attribute__((nonnull(1,2)));
/*
Helper methods to deal with thread local storage.
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 4a1117a88fe..949a9eae0d7 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -18691,7 +18691,15 @@ void lock_wait_wsrep_kill(trx_t *bf_trx, ulong thd_id, trx_id_t trx_id)
lock_sys.cancel_lock_wait_for_trx(vtrx);
DEBUG_SYNC(bf_thd, "before_wsrep_thd_abort");
- wsrep_thd_bf_abort(bf_thd, vthd, true);
+ if (!wsrep_thd_bf_abort(bf_thd, vthd, true))
+ {
+ wsrep_thd_LOCK(vthd);
+ wsrep_thd_set_wsrep_aborter(NULL, vthd);
+ wsrep_thd_UNLOCK(vthd);
+
+ WSREP_DEBUG("wsrep_thd_bf_abort has failed, victim %lu will survive",
+ thd_get_thread_id(vthd));
+ }
}
wsrep_thd_kill_UNLOCK(vthd);
}
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 46cfb6e5c88..9577dfc62aa 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -693,22 +693,31 @@ lock_rec_has_to_wait(
#endif /* HAVE_REPLICATION */
#ifdef WITH_WSREP
- /* New lock request from a transaction is using unique key
- scan and this transaction is a wsrep high priority transaction
- (brute force). If conflicting transaction is also wsrep high
- priority transaction we should avoid lock conflict because
- ordering of these transactions is already decided and
- conflicting transaction will be later replayed. */
- if (trx->is_wsrep_UK_scan()
- && wsrep_thd_is_BF(lock2->trx->mysql_thd, false)) {
- return false;
- }
+ /* New lock request from a transaction is using unique key
+ scan and this transaction is a wsrep high priority transaction
+ (brute force). If conflicting transaction is also wsrep high
+ priority transaction we should avoid lock conflict because
+ ordering of these transactions is already decided and
+ conflicting transaction will be later replayed. */
+ if (trx->is_wsrep_UK_scan()
+ && wsrep_thd_is_BF(lock2->trx->mysql_thd, false)) {
+ return false;
+ }
+
+ /* if BF-BF conflict, we have to look at write set order */
+ if (trx->is_wsrep() &&
+ (type_mode & LOCK_MODE_MASK) == LOCK_X &&
+ (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X &&
+ wsrep_thd_order_before(trx->mysql_thd,
+ lock2->trx->mysql_thd)) {
+ return false;
+ }
- /* We very well can let bf to wait normally as other
- BF will be replayed in case of conflict. For debug
- builds we will do additional sanity checks to catch
- unsupported bf wait if any. */
- ut_d(wsrep_assert_no_bf_bf_wait(lock2, trx));
+ /* We very well can let bf to wait normally as other
+ BF will be replayed in case of conflict. For debug
+ builds we will do additional sanity checks to catch
+ unsupported bf wait if any. */
+ ut_d(wsrep_assert_no_bf_bf_wait(lock2, trx));
#endif /* WITH_WSREP */
return true;
@@ -1600,6 +1609,14 @@ lock_rec_has_to_wait_in_queue(const hash_cell_t &cell, const lock_t *wait_lock)
if (heap_no < lock_rec_get_n_bits(lock)
&& (p[bit_offset] & bit_mask)
&& lock_has_to_wait(wait_lock, lock)) {
+#ifdef WITH_WSREP
+ if (lock->trx->is_wsrep() &&
+ wsrep_thd_order_before(wait_lock->trx->mysql_thd,
+ lock->trx->mysql_thd)) {
+ /* don't wait for another BF lock */
+ continue;
+ }
+#endif
return(lock);
}
}