1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge branch '10.7' into 10.8

This commit is contained in:
Oleksandr Byelkin
2023-01-18 16:37:40 +01:00
53 changed files with 793 additions and 130 deletions

View File

@@ -9,10 +9,8 @@ MariaDB Corporation https://www.mariadb.com (2013)
Microsoft https://microsoft.com/ (2017) Microsoft https://microsoft.com/ (2017)
ServiceNow https://servicenow.com (2019) ServiceNow https://servicenow.com (2019)
SIT https://sit.org (2022) SIT https://sit.org (2022)
Tencent Cloud https://cloud.tencent.com (2017)
Development Bank of Singapore https://dbs.com (2016) Development Bank of Singapore https://dbs.com (2016)
IBM https://www.ibm.com (2017) IBM https://www.ibm.com (2017)
Visma https://visma.com (2015)
Automattic https://automattic.com (2019) Automattic https://automattic.com (2019)
Galera Cluster https://galeracluster.com (2020) Galera Cluster https://galeracluster.com (2020)
Percona https://www.percona.com (2018) Percona https://www.percona.com (2018)

View File

@@ -54,8 +54,8 @@ MACRO(BUNDLE_PCRE2)
ExternalProject_Add( ExternalProject_Add(
pcre2 pcre2
PREFIX "${dir}" PREFIX "${dir}"
URL "https://github.com/PhilipHazel/pcre2/releases/download/pcre2-10.40/pcre2-10.40.zip" URL "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.42/pcre2-10.42.zip"
URL_MD5 798698846982ce171d881ed0d7535c2a URL_MD5 fe90992fbfb03f854bd9f344074f49eb
INSTALL_COMMAND "" INSTALL_COMMAND ""
CMAKE_ARGS CMAKE_ARGS
"-DCMAKE_WARN_DEPRECATED=FALSE" "-DCMAKE_WARN_DEPRECATED=FALSE"

View File

@@ -157,6 +157,8 @@ IF(WOLFSSL_X86_64_BUILD)
${WOLFCRYPT_SRCDIR}/sha512_asm.S ${WOLFCRYPT_SRCDIR}/sha512_asm.S
${WOLFCRYPT_SRCDIR}/sha256_asm.S) ${WOLFCRYPT_SRCDIR}/sha256_asm.S)
ADD_DEFINITIONS(-maes -msse4.2 -mpclmul) ADD_DEFINITIONS(-maes -msse4.2 -mpclmul)
# WolfSSL 5.5.4 bug - user_settings.h not included into aes_asm.S
SET_PROPERTY(SOURCE ${WOLFCRYPT_SRCDIR}/aes_asm.S APPEND PROPERTY COMPILE_OPTIONS "-DWOLFSSL_X86_64_BUILD")
ENDIF() ENDIF()
ENDIF() ENDIF()

View File

@@ -183,7 +183,9 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
DROP PROCEDURE sp; DROP PROCEDURE sp;
DROP TABLE t1; DROP TABLE t1;
#
# End of 10.2 tests # End of 10.2 tests
#
create table t1 (a int check (a>10)) select 100 as 'a'; create table t1 (a int check (a>10)) select 100 as 'a';
show create table t1; show create table t1;
Table Create Table Table Create Table
@@ -201,3 +203,35 @@ a
19 19
ccc ccc
drop table t1; 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;

View File

@@ -151,7 +151,9 @@ show create table t1;
DROP PROCEDURE sp; DROP PROCEDURE sp;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # End of 10.2 tests --echo # End of 10.2 tests
--echo #
# #
# Check that we don't lose constraints as part of CREATE ... SELECT # 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 (""); insert into t1 values ("");
select * from t1; select * from t1;
drop table 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;

View File

@@ -1611,6 +1611,18 @@ SELECT json_object('a', coalesce(json_object('b', 'c')));
json_object('a', coalesce(json_object('b', 'c'))) json_object('a', coalesce(json_object('b', 'c')))
{"a": {"b": "c"}} {"a": {"b": "c"}}
# #
# MDEV-26392: Crash with json_get_path_next and 10.5.12
#
CREATE TABLE arrNestTest (
id VARCHAR(80) AS (JSON_COMPACT(JSON_EXTRACT(doc, "$._id"))) UNIQUE KEY,
doc JSON,
CONSTRAINT id_not_null CHECK(id IS NOT NULL));
INSERT INTO test.arrNestTest (doc) VALUES ('{ "_id" : { "$oid" : "611c0a463b150154132f6636" }, "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : 1.0 } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] }');
SELECT * FROM arrNestTest;
id doc
{"$oid":"611c0a463b150154132f6636"} { "_id" : { "$oid" : "611c0a463b150154132f6636" }, "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : 1.0 } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] }
DROP TABLE arrNestTest;
#
# MDEV-26054 Server crashes in Item_func_json_arrayagg::get_str_from_field # MDEV-26054 Server crashes in Item_func_json_arrayagg::get_str_from_field
# #
CREATE TABLE t (a VARCHAR(8)); CREATE TABLE t (a VARCHAR(8));

View File

@@ -1054,6 +1054,18 @@ DROP TABLE t2;
SELECT json_object('a', if(1, json_object('b', 'c'), json_object('e', 'f'))); SELECT json_object('a', if(1, json_object('b', 'c'), json_object('e', 'f')));
SELECT json_object('a', coalesce(json_object('b', 'c'))); SELECT json_object('a', coalesce(json_object('b', 'c')));
--echo #
--echo # MDEV-26392: Crash with json_get_path_next and 10.5.12
--echo #
CREATE TABLE arrNestTest (
id VARCHAR(80) AS (JSON_COMPACT(JSON_EXTRACT(doc, "$._id"))) UNIQUE KEY,
doc JSON,
CONSTRAINT id_not_null CHECK(id IS NOT NULL));
INSERT INTO test.arrNestTest (doc) VALUES ('{ "_id" : { "$oid" : "611c0a463b150154132f6636" }, "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : [ { "a" : 1.0 } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] } ] }');
SELECT * FROM arrNestTest;
DROP TABLE arrNestTest;
--echo # --echo #
--echo # MDEV-26054 Server crashes in Item_func_json_arrayagg::get_str_from_field --echo # MDEV-26054 Server crashes in Item_func_json_arrayagg::get_str_from_field

View File

@@ -3407,3 +3407,20 @@ id select_type table type possible_keys key key_len ref rows Extra
drop table t1,t2,t3; drop table t1,t2,t3;
drop table t1000,t10,t03; drop table t1000,t10,t03;
# End of 10.3 tests # 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

View File

@@ -1820,3 +1820,18 @@ drop table t1,t2,t3;
drop table t1000,t10,t03; drop table t1000,t10,t03;
--echo # End of 10.3 tests --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

View File

@@ -2325,6 +2325,38 @@ DROP TABLE federated.t1;
connection slave; connection slave;
DROP TABLE federated.t1; DROP TABLE federated.t1;
connection default; 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; connection master;
DROP TABLE IF EXISTS federated.t1; DROP TABLE IF EXISTS federated.t1;
DROP DATABASE IF EXISTS federated; DROP DATABASE IF EXISTS federated;

View File

@@ -2060,4 +2060,34 @@ connection slave;
DROP TABLE federated.t1; DROP TABLE federated.t1;
connection default; 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; source include/federated_cleanup.inc;

View File

@@ -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;

View File

@@ -20,8 +20,6 @@ connection node_1;
include/diff_servers.inc [servers=1 2] include/diff_servers.inc [servers=1 2]
connection node_1; connection node_1;
CALL mtr.add_suppression("Skipped GCache ring buffer recovery"); CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
include/assert_grep.inc [async IST sender starting to serve]
connection node_2; connection node_2;
CALL mtr.add_suppression("Skipped GCache ring buffer recovery"); CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
include/assert_grep.inc [Recovering GCache ring buffer: found gapless sequence]
DROP TABLE t1; DROP TABLE t1;

View File

@@ -134,8 +134,6 @@ connection node_1;
call mtr.add_suppression("Error in Log_event::read_log_event():.*"); 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("conflict state 7 after post commit");
CALL mtr.add_suppression("Skipped GCache ring buffer recovery"); CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
include/assert_grep.inc [async IST sender starting to serve]
connection node_2; connection node_2;
call mtr.add_suppression("Error in Log_event::read_log_event():.*"); call mtr.add_suppression("Error in Log_event::read_log_event():.*");
CALL mtr.add_suppression("Skipped GCache ring buffer recovery"); CALL mtr.add_suppression("Skipped GCache ring buffer recovery");
include/assert_grep.inc [Recovering GCache ring buffer: found gapless sequence]

View File

@@ -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;

View File

@@ -20,8 +20,8 @@ SET GLOBAL wsrep_mode='A';
ERROR 42000: Variable 'wsrep_mode' can't be set to the value of 'A' ERROR 42000: Variable 'wsrep_mode' can't be set to the value of 'A'
SET GLOBAL wsrep_mode=NULL; SET GLOBAL wsrep_mode=NULL;
ERROR 42000: Variable 'wsrep_mode' can't be set to the value of 'NULL' ERROR 42000: Variable 'wsrep_mode' can't be set to the value of 'NULL'
SET GLOBAL wsrep_mode=64; SET GLOBAL wsrep_mode=128;
ERROR 42000: Variable 'wsrep_mode' can't be set to the value of '64' ERROR 42000: Variable 'wsrep_mode' can't be set to the value of '128'
SET GLOBAL wsrep_mode=REQUIRED_PRIMARY_KEY,REPLICATE_MYISAM; SET GLOBAL wsrep_mode=REQUIRED_PRIMARY_KEY,REPLICATE_MYISAM;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
SET GLOBAL wsrep_mode=1; SET GLOBAL wsrep_mode=1;

View File

@@ -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]

View File

@@ -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;

View File

@@ -54,24 +54,7 @@ INSERT INTO t1 VALUES (3);
# Warning happens when the cluster is started for the first time # Warning happens when the cluster is started for the first time
CALL mtr.add_suppression("Skipped GCache ring buffer recovery"); 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 --connection node_2
CALL mtr.add_suppression("Skipped GCache ring buffer recovery"); 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; DROP TABLE t1;

View File

@@ -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 # Warning happens when the cluster is started for the first time
CALL mtr.add_suppression("Skipped GCache ring buffer recovery"); 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 --connection node_2
call mtr.add_suppression("Error in Log_event::read_log_event():.*"); call mtr.add_suppression("Error in Log_event::read_log_event():.*");
CALL mtr.add_suppression("Skipped GCache ring buffer recovery"); 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

View File

@@ -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;

View File

@@ -22,7 +22,7 @@ SET GLOBAL wsrep_mode='A';
--error ER_WRONG_VALUE_FOR_VAR --error ER_WRONG_VALUE_FOR_VAR
SET GLOBAL wsrep_mode=NULL; SET GLOBAL wsrep_mode=NULL;
--error ER_WRONG_VALUE_FOR_VAR --error ER_WRONG_VALUE_FOR_VAR
SET GLOBAL wsrep_mode=64; SET GLOBAL wsrep_mode=128;
--error ER_PARSE_ERROR --error ER_PARSE_ERROR
SET GLOBAL wsrep_mode=REQUIRED_PRIMARY_KEY,REPLICATE_MYISAM; SET GLOBAL wsrep_mode=REQUIRED_PRIMARY_KEY,REPLICATE_MYISAM;
# #

View File

@@ -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.");

View File

@@ -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

View File

@@ -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.");

View File

@@ -8,6 +8,8 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 BLOB) ENGINE=InnoDB;
# Introduce inconsistency # Introduce inconsistency
--connection node_2 --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; SET SESSION wsrep_on=OFF;
--eval INSERT INTO t1 VALUES ($inconsistent_fragment, 'X') --eval INSERT INTO t1 VALUES ($inconsistent_fragment, 'X')
SET SESSION wsrep_on=ON; SET SESSION wsrep_on=ON;

View File

@@ -944,6 +944,8 @@ DROP TABLE t1;
# #
# TODO: enable them after MDEV-16417 is finished # TODO: enable them after MDEV-16417 is finished
create or replace table t1 (a int primary key) engine=innodb; 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; 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` 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; create or replace table t1 (f1 int, f2 date, f3 date, key(f1,f3,f2)) engine=innodb;

View File

@@ -970,6 +970,8 @@ DROP TABLE t1;
--echo # TODO: enable them after MDEV-16417 is finished --echo # TODO: enable them after MDEV-16417 is finished
create or replace table t1 (a int primary key) engine=innodb; create or replace table t1 (a int primary key) engine=innodb;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED --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 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; create or replace table t1 (f1 int, f2 date, f3 date, key(f1,f3,f2)) engine=innodb;

View File

@@ -342,7 +342,7 @@ VARIABLE_COMMENT Set of WSREP features that are enabled.
NUMERIC_MIN_VALUE NULL NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST STRICT_REPLICATION,BINLOG_ROW_FORMAT_ONLY,REQUIRED_PRIMARY_KEY,REPLICATE_MYISAM,REPLICATE_ARIA,DISALLOW_LOCAL_GTID ENUM_VALUE_LIST STRICT_REPLICATION,BINLOG_ROW_FORMAT_ONLY,REQUIRED_PRIMARY_KEY,REPLICATE_MYISAM,REPLICATE_ARIA,DISALLOW_LOCAL_GTID,BF_ABORT_MARIABACKUP
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
GLOBAL_VALUE_PATH NULL GLOBAL_VALUE_PATH NULL

View File

@@ -35,9 +35,10 @@
#include "sql_handler.h" // mysql_ha_cleanup_no_free #include "sql_handler.h" // mysql_ha_cleanup_no_free
#include <my_sys.h> #include <my_sys.h>
#include <strfunc.h> // strconvert() #include <strfunc.h> // strconvert()
#include "wsrep_mysqld.h" #include "debug_sync.h"
#ifdef WITH_WSREP #ifdef WITH_WSREP
#include "wsrep_server_state.h" #include "wsrep_server_state.h"
#include "wsrep_mysqld.h"
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
static const char *stage_names[]= static const char *stage_names[]=
@@ -292,17 +293,27 @@ static bool backup_block_ddl(THD *thd)
#ifdef WITH_WSREP #ifdef WITH_WSREP
/* /*
We desync the node for BACKUP STAGE because applier threads if user is specifically choosing to allow BF aborting for BACKUP STAGE BLOCK_DDL lock
holder, then do not desync and pause the node from cluster replication.
e.g. mariabackup uses BACKUP STATE BLOCK_DDL; and will be abortable by this.
But, If node is processing as SST donor or WSREP_MODE_BF_MARIABACKUP mode is not set,
we desync the node for BACKUP STAGE because applier threads
bypass backup MDL locks (see MDL_lock::can_grant_lock) bypass backup MDL locks (see MDL_lock::can_grant_lock)
*/ */
if (WSREP_NNULL(thd)) if (WSREP_NNULL(thd))
{ {
Wsrep_server_state &server_state= Wsrep_server_state::instance(); Wsrep_server_state &server_state= Wsrep_server_state::instance();
if (!wsrep_check_mode(WSREP_MODE_BF_MARIABACKUP) ||
server_state.state() == Wsrep_server_state::s_donor)
{
if (server_state.desync_and_pause().is_undefined()) { if (server_state.desync_and_pause().is_undefined()) {
DBUG_RETURN(1); DBUG_RETURN(1);
} }
thd->wsrep_desynced_backup_stage= true; thd->wsrep_desynced_backup_stage= true;
} }
else
WSREP_INFO("Server not desynched from group because WSREP_MODE_BF_MARIABACKUP used.");
}
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
/* /*
@@ -341,6 +352,18 @@ static bool backup_block_ddl(THD *thd)
/* There can't be anything more that needs to be logged to ddl log */ /* There can't be anything more that needs to be logged to ddl log */
THD_STAGE_INFO(thd, org_stage); THD_STAGE_INFO(thd, org_stage);
stop_ddl_logging(); stop_ddl_logging();
#ifdef WITH_WSREP
// Allow tests to block the applier thread using the DBUG facilities
DBUG_EXECUTE_IF("sync.wsrep_after_mdl_block_ddl",
{
const char act[]=
"now "
"signal signal.wsrep_apply_toi";
DBUG_ASSERT(!debug_sync_set_action(thd,
STRING_WITH_LEN(act)));
};);
#endif /* WITH_WSREP */
DBUG_RETURN(0); DBUG_RETURN(0);
err: err:
THD_STAGE_INFO(thd, org_stage); THD_STAGE_INFO(thd, org_stage);
@@ -400,7 +423,8 @@ bool backup_end(THD *thd)
thd->current_backup_stage= BACKUP_FINISHED; thd->current_backup_stage= BACKUP_FINISHED;
thd->mdl_context.release_lock(old_ticket); thd->mdl_context.release_lock(old_ticket);
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (WSREP_NNULL(thd) && thd->wsrep_desynced_backup_stage) if (WSREP_NNULL(thd) && thd->wsrep_desynced_backup_stage &&
!wsrep_check_mode(WSREP_MODE_BF_MARIABACKUP))
{ {
Wsrep_server_state &server_state= Wsrep_server_state::instance(); Wsrep_server_state &server_state= Wsrep_server_state::instance();
THD_STAGE_INFO(thd, stage_waiting_flow); THD_STAGE_INFO(thd, stage_waiting_flow);

View File

@@ -558,7 +558,6 @@ static inline const char *vcol_type_name(enum_vcol_info_type type)
#define VCOL_AUTO_INC 16 #define VCOL_AUTO_INC 16
#define VCOL_IMPOSSIBLE 32 #define VCOL_IMPOSSIBLE 32
#define VCOL_NEXTVAL 64 /* NEXTVAL is not implemented for vcols */ #define VCOL_NEXTVAL 64 /* NEXTVAL is not implemented for vcols */
#define VCOL_CHECK_CONSTRAINT_IF_NOT_EXISTS 128
#define VCOL_NOT_STRICTLY_DETERMINISTIC \ #define VCOL_NOT_STRICTLY_DETERMINISTIC \
(VCOL_NON_DETERMINISTIC | VCOL_TIME_FUNC | VCOL_SESSION_FUNC) (VCOL_NON_DETERMINISTIC | VCOL_TIME_FUNC | VCOL_SESSION_FUNC)
@@ -590,6 +589,7 @@ public:
bool stored_in_db; bool stored_in_db;
bool utf8; /* Already in utf8 */ bool utf8; /* Already in utf8 */
bool automatic_name; bool automatic_name;
bool if_not_exists;
Item *expr; Item *expr;
Lex_ident name; /* Name of constraint */ Lex_ident name; /* Name of constraint */
/* see VCOL_* (VCOL_FIELD_REF, ...) */ /* see VCOL_* (VCOL_FIELD_REF, ...) */

View File

@@ -357,9 +357,9 @@ enum chf_create_flags {
Rowid's are not comparable. This is set if the rowid is unique to the 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 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 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: the table:
ror scans or filtering ror scans, filtering or duplicate weedout
*/ */
#define HA_NON_COMPARABLE_ROWID (1ULL << 60) #define HA_NON_COMPARABLE_ROWID (1ULL << 60)

View File

@@ -3476,7 +3476,7 @@ bool Item_field::is_null_result()
bool Item_field::eq(const Item *item, bool binary_cmp) const 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) if (real_item2->type() != FIELD_ITEM)
return 0; return 0;

View File

@@ -2103,6 +2103,7 @@ public:
virtual Item *copy_or_same(THD *thd) { return this; } virtual Item *copy_or_same(THD *thd) { return this; }
virtual Item *copy_andor_structure(THD *thd) { return this; } virtual Item *copy_andor_structure(THD *thd) { return this; }
virtual Item *real_item() { 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 *get_tmp_table_item(THD *thd) { return copy_or_same(thd); }
virtual Item *make_odbc_literal(THD *thd, const LEX_CSTRING *typestr) virtual Item *make_odbc_literal(THD *thd, const LEX_CSTRING *typestr)
{ {
@@ -5593,7 +5594,7 @@ public:
{ return ref ? (*ref)->type() : REF_ITEM; } { return ref ? (*ref)->type() : REF_ITEM; }
bool eq(const Item *item, bool binary_cmp) const override 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); return ref && (*ref)->eq(it, binary_cmp);
} }
void save_val(Field *to) override; void save_val(Field *to) override;
@@ -5949,7 +5950,7 @@ public:
{ orig_item->make_send_field(thd, field); } { orig_item->make_send_field(thd, field); }
bool eq(const Item *item, bool binary_cmp) const override 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); return orig_item->eq(it, binary_cmp);
} }
void fix_after_pullout(st_select_lex *new_parent, Item **refptr, bool merge) void fix_after_pullout(st_select_lex *new_parent, Item **refptr, bool merge)
@@ -7830,7 +7831,7 @@ public:
{ m_item->make_send_field(thd, field); } { m_item->make_send_field(thd, field); }
bool eq(const Item *item, bool binary_cmp) const 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); return m_item->eq(it, binary_cmp);
} }
void fix_after_pullout(st_select_lex *new_parent, Item **refptr, bool merge) void fix_after_pullout(st_select_lex *new_parent, Item **refptr, bool merge)

View File

@@ -1064,7 +1064,7 @@ String *Item_func_json_extract::read_json(String *str,
if (!possible_multiple_values) if (!possible_multiple_values)
{ {
/* Loop to the end of the JSON just to make sure it's valid. */ /* Loop to the end of the JSON just to make sure it's valid. */
while (json_get_path_next(&je, &p) == 0) {} while (json_scan_next(&je) == 0) {}
break; break;
} }
} }
@@ -1688,7 +1688,7 @@ bool is_json_type(const Item *item)
if (Type_handler_json_common::is_json_type_handler(item->type_handler())) if (Type_handler_json_common::is_json_type_handler(item->type_handler()))
return true; return true;
const Item_func_conv_charset *func; 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; return false;
item= func->arguments()[0]; item= func->arguments()[0];
} }

View File

@@ -1747,10 +1747,9 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
#ifdef WITH_WSREP #ifdef WITH_WSREP
/* /*
Approve lock request in BACKUP namespace for BF threads. Approve lock request in BACKUP namespace for BF threads.
We should get rid of this code and forbid FTWRL/BACKUP statements
when wsrep is active.
*/ */
if ((wsrep_thd_is_toi(requestor_ctx->get_thd()) || if (!wsrep_check_mode(WSREP_MODE_BF_MARIABACKUP) &&
(wsrep_thd_is_toi(requestor_ctx->get_thd()) ||
wsrep_thd_is_applying(requestor_ctx->get_thd())) && wsrep_thd_is_applying(requestor_ctx->get_thd())) &&
key.mdl_namespace() == MDL_key::BACKUP) key.mdl_namespace() == MDL_key::BACKUP)
{ {

View File

@@ -664,6 +664,17 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
DBUG_RETURN(-1); 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")); DBUG_PRINT("info", ("Checking if subq can be converted to semi-join"));
/* /*
@@ -685,6 +696,9 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
11. It is first optimisation (the subquery could be moved from ON 11. It is first optimisation (the subquery could be moved from ON
clause during first optimisation and then be considered for SJ clause during first optimisation and then be considered for SJ
on the second when it is too late) 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) && if (optimizer_flag(thd, OPTIMIZER_SWITCH_SEMIJOIN) &&
in_subs && // 1 in_subs && // 1
@@ -699,7 +713,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
!((join->select_options | // 10 !((join->select_options | // 10
select_lex->outer_select()->join->select_options) // 10 select_lex->outer_select()->join->select_options) // 10
& SELECT_STRAIGHT_JOIN) && // 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")); DBUG_PRINT("info", ("Subquery is semi-join conversion candidate"));
@@ -3557,6 +3572,9 @@ bool Duplicate_weedout_picker::check_qep(JOIN *join,
} }
else 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); sj_outer_fanout= COST_MULT(sj_outer_fanout, p->records_read);
temptable_rec_size += p->table->table->file->ref_length; temptable_rec_size += p->table->table->file->ref_length;
} }

View File

@@ -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 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 it under the terms of the GNU General Public License as published by
@@ -241,7 +241,7 @@ extern "C" my_bool wsrep_thd_bf_abort(THD *bf_thd, THD *victim_thd,
victim_thd->awake_no_mutex(KILL_QUERY); victim_thd->awake_no_mutex(KILL_QUERY);
mysql_mutex_unlock(&victim_thd->LOCK_thd_data); mysql_mutex_unlock(&victim_thd->LOCK_thd_data);
} else { } else {
WSREP_DEBUG("wsrep_thd_bf_abort skipped awake"); WSREP_DEBUG("wsrep_thd_bf_abort skipped awake, signal %d", signal);
} }
return ret; return ret;
} }
@@ -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) 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", WSREP_DEBUG("BF conflict, order: %lld %lld\n",
(long long)wsrep_thd_trx_seqno(left), (long long)wsrep_thd_trx_seqno(left),
(long long)wsrep_thd_trx_seqno(right)); (long long)wsrep_thd_trx_seqno(right));
@@ -277,7 +279,6 @@ extern "C" my_bool wsrep_thd_is_aborting(const MYSQL_THD thd)
return (cs.state() == wsrep::client_state::s_exec || return (cs.state() == wsrep::client_state::s_exec ||
cs.state() == wsrep::client_state::s_result); cs.state() == wsrep::client_state::s_result);
case wsrep::transaction::s_aborting: case wsrep::transaction::s_aborting:
case wsrep::transaction::s_aborted:
return true; return true;
default: default:
return false; return false;
@@ -369,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) 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); 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) if (victim_thd->wsrep_aborter && victim_thd->wsrep_aborter != bf_thd->thread_id)
{ {
return true; 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; return false;
} }

View File

@@ -5458,8 +5458,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. the caller should guarantee that the BF state won't change.
(e.g. InnoDB does it by keeping lock_sys.mutex locked) (e.g. InnoDB does it by keeping lock_sys.mutex locked)
*/ */
if (WSREP_ON && wsrep_thd_is_BF(thd, false) && if (WSREP_ON &&
wsrep_thd_is_BF(other_thd, false)) wsrep_thd_order_before(thd, other_thd))
return 0; return 0;
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
rgi= thd->rgi_slave; rgi= thd->rgi_slave;

View File

@@ -4397,7 +4397,7 @@ public:
bool if_not_exists) bool if_not_exists)
{ {
constr->name= name; 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); alter_info.check_constraint_list.push_back(constr);
return false; return false;
} }

View File

@@ -407,7 +407,7 @@ void JOIN::init(THD *thd_arg, List<Item> &fields_arg,
table_count= 0; table_count= 0;
top_join_tab_count= 0; top_join_tab_count= 0;
const_tables= 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; aggr_tables= 0;
eliminated_tables= 0; eliminated_tables= 0;
join_list= 0; join_list= 0;
@@ -2474,7 +2474,7 @@ JOIN::optimize_inner()
/* /*
We have to remove constants and duplicates from group_list before We have to remove constants and duplicates from group_list before
calling make_join_statistics() as this may call get_best_group_min_max() 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) if (group_list && table_count == 1)
{ {
@@ -5861,7 +5861,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
caller to abort with a zero row result. caller to abort with a zero row result.
*/ */
TABLE_LIST *emb= s->table->pos_in_table_list->embedding; 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 all tables in a multi-table join nest as const */
mark_join_nest_as_const(join, emb, &found_const_table_map, mark_join_nest_as_const(join, emb, &found_const_table_map,

View File

@@ -1254,6 +1254,8 @@ public:
table_map outer_join; table_map outer_join;
/* Bitmap of tables used in the select list items */ /* Bitmap of tables used in the select list items */
table_map select_list_used_tables; 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; ha_rows send_records,found_records,join_examined_rows, accepted_rows;
/* /*

View File

@@ -3780,7 +3780,7 @@ without_overlaps_err:
my_error(ER_TOO_LONG_IDENT, MYF(0), check->name.str); my_error(ER_TOO_LONG_IDENT, MYF(0), check->name.str);
DBUG_RETURN(TRUE); 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); DBUG_RETURN(TRUE);
} }
} }
@@ -6225,10 +6225,8 @@ remove_key:
while ((check=it++)) while ((check=it++))
{ {
if (!(check->flags & VCOL_CHECK_CONSTRAINT_IF_NOT_EXISTS) && if (!check->if_not_exists && check->name.length)
check->name.length)
continue; continue;
check->flags= 0;
for (c= share->field_check_constraints; for (c= share->field_check_constraints;
c < share->table_check_constraints ; c++) c < share->table_check_constraints ; c++)
{ {

View File

@@ -6036,6 +6036,7 @@ static const char *wsrep_mode_names[]=
"REPLICATE_MYISAM", "REPLICATE_MYISAM",
"REPLICATE_ARIA", "REPLICATE_ARIA",
"DISALLOW_LOCAL_GTID", "DISALLOW_LOCAL_GTID",
"BF_ABORT_MARIABACKUP",
NullS NullS
}; };
static Sys_var_set Sys_wsrep_mode( static Sys_var_set Sys_wsrep_mode(

View File

@@ -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 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 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 */ transactional locks */
DBUG_ASSERT(!orig_thd->mdl_context.has_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 */ /* Make a shadow copy of diagnostics area and reset */
m_da_shadow.status= orig_thd->get_stmt_da()->status(); m_da_shadow.status= orig_thd->get_stmt_da()->status();
if (m_da_shadow.status == Diagnostics_area::DA_OK) 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() Wsrep_replayer_service::~Wsrep_replayer_service()
{ {
THD* replayer_thd= m_thd;
THD* orig_thd= m_orig_thd;
/* Switch execution context back to original. */ /* Switch execution context back to original. */
wsrep_after_apply(replayer_thd); wsrep_after_apply(m_thd);
wsrep_after_command_ignore_result(replayer_thd); wsrep_after_command_ignore_result(m_thd);
wsrep_close(replayer_thd); wsrep_close(m_thd);
wsrep_reset_threadvars(replayer_thd); wsrep_reset_threadvars(m_thd);
wsrep_store_threadvars(orig_thd); wsrep_store_threadvars(m_orig_thd);
DBUG_ASSERT(!orig_thd->get_stmt_da()->is_sent()); DBUG_ASSERT(!m_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_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) if (m_replay_status == wsrep::provider::success)
{ {
DBUG_ASSERT(replayer_thd->wsrep_cs().current_error() == wsrep::e_success); DBUG_ASSERT(m_thd->wsrep_cs().current_error() == wsrep::e_success);
orig_thd->reset_kill_query(); m_orig_thd->reset_kill_query();
my_ok(orig_thd, m_da_shadow.affected_rows, m_da_shadow.last_insert_id); 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) 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 else
{ {
DBUG_ASSERT(0); DBUG_ASSERT(0);
WSREP_ERROR("trx_replay failed for: %d, schema: %s, query: %s", WSREP_ERROR("trx_replay failed for: %d, schema: %s, query: %s",
m_replay_status, 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); unireg_abort(1);
} }
} }

View File

@@ -362,10 +362,12 @@ static void wsrep_log_cb(wsrep::log::level level,
void wsrep_init_gtid() void wsrep_init_gtid()
{ {
wsrep_server_gtid_t stored_gtid= wsrep_get_SE_checkpoint<wsrep_server_gtid_t>(); 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) if (stored_gtid.server_id == 0)
{ {
rpl_gtid wsrep_last_gtid; rpl_gtid wsrep_last_gtid;
stored_gtid.domain_id= wsrep_gtid_server.domain_id;
if (mysql_bin_log.is_open() && if (mysql_bin_log.is_open() &&
mysql_bin_log.lookup_domain_in_binlog_state(stored_gtid.domain_id, mysql_bin_log.lookup_domain_in_binlog_state(stored_gtid.domain_id,
&wsrep_last_gtid)) &wsrep_last_gtid))
@@ -3078,6 +3080,11 @@ void wsrep_handle_mdl_conflict(MDL_context *requestor_ctx,
THD_STAGE_INFO(request_thd, stage_waiting_ddl); THD_STAGE_INFO(request_thd, stage_waiting_ddl);
ticket->wsrep_report(wsrep_debug); ticket->wsrep_report(wsrep_debug);
mysql_mutex_unlock(&granted_thd->LOCK_thd_data); mysql_mutex_unlock(&granted_thd->LOCK_thd_data);
if (granted_thd->current_backup_stage != BACKUP_FINISHED &&
wsrep_check_mode(WSREP_MODE_BF_MARIABACKUP))
{
wsrep_abort_thd(request_thd, granted_thd, 1);
}
} }
else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE) else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE)
{ {

View File

@@ -128,7 +128,8 @@ enum enum_wsrep_mode {
WSREP_MODE_REQUIRED_PRIMARY_KEY= (1ULL << 2), WSREP_MODE_REQUIRED_PRIMARY_KEY= (1ULL << 2),
WSREP_MODE_REPLICATE_MYISAM= (1ULL << 3), WSREP_MODE_REPLICATE_MYISAM= (1ULL << 3),
WSREP_MODE_REPLICATE_ARIA= (1ULL << 4), WSREP_MODE_REPLICATE_ARIA= (1ULL << 4),
WSREP_MODE_DISALLOW_LOCAL_GTID= (1ULL << 5) WSREP_MODE_DISALLOW_LOCAL_GTID= (1ULL << 5),
WSREP_MODE_BF_MARIABACKUP= (1ULL << 6)
}; };
// Streaming Replication // Streaming Replication

View File

@@ -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 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 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"); 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); mysql_mutex_lock(&victim_thd->LOCK_thd_data);
/* Note that when you use RSU node is desynced from cluster, thus WSREP(thd) /* Note that when you use RSU node is desynced from cluster, thus WSREP(thd)
might not be true. 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_ON || bf_thd->variables.wsrep_OSU_method == WSREP_OSU_RSU) &&
wsrep_thd_is_toi(bf_thd))) && wsrep_thd_is_toi(bf_thd))) &&
victim_thd &&
!wsrep_thd_is_aborting(victim_thd)) !wsrep_thd_is_aborting(victim_thd))
{ {
WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu", (bf_thd) ? WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu",
(long long)bf_thd->real_id : 0, (long long)victim_thd->real_id); (long long)bf_thd->real_id, (long long)victim_thd->real_id);
mysql_mutex_unlock(&victim_thd->LOCK_thd_data); mysql_mutex_unlock(&victim_thd->LOCK_thd_data);
ha_abort_transaction(bf_thd, victim_thd, signal); ha_abort_transaction(bf_thd, victim_thd, signal);
mysql_mutex_lock(&victim_thd->LOCK_thd_data); DBUG_RETURN(1);
} }
else 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); mysql_mutex_unlock(&victim_thd->LOCK_thd_data);
@@ -375,6 +380,14 @@ bool wsrep_bf_abort(THD* bf_thd, THD* victim_thd)
have acquired MDL locks (due to DDL execution), and this has caused BF conflict. have acquired MDL locks (due to DDL execution), and this has caused BF conflict.
such case does not require aborting in wsrep or replication provider state. such case does not require aborting in wsrep or replication provider state.
*/ */
if (victim_thd->current_backup_stage != BACKUP_FINISHED &&
wsrep_check_mode(WSREP_MODE_BF_MARIABACKUP))
{
WSREP_DEBUG("killing connection for non wsrep session");
mysql_mutex_lock(&victim_thd->LOCK_thd_data);
victim_thd->awake_no_mutex(KILL_CONNECTION);
mysql_mutex_unlock(&victim_thd->LOCK_thd_data);
}
return false; return false;
} }

View File

@@ -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 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 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(); void wsrep_create_rollbacker();
bool wsrep_bf_abort(THD* bf_thd, THD* victim_thd); 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. Helper methods to deal with thread local storage.

View File

@@ -18599,7 +18599,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); lock_sys.cancel_lock_wait_for_trx(vtrx);
DEBUG_SYNC(bf_thd, "before_wsrep_thd_abort"); 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); wsrep_thd_kill_UNLOCK(vthd);
} }

View File

@@ -704,6 +704,15 @@ lock_rec_has_to_wait(
return 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 /* We very well can let bf to wait normally as other
BF will be replayed in case of conflict. For debug BF will be replayed in case of conflict. For debug
builds we will do additional sanity checks to catch builds we will do additional sanity checks to catch
@@ -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) if (heap_no < lock_rec_get_n_bits(lock)
&& (p[bit_offset] & bit_mask) && (p[bit_offset] & bit_mask)
&& lock_has_to_wait(wait_lock, lock)) { && 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); return(lock);
} }
} }