mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Merge 10.4 into 10.5
This commit is contained in:
16
mysql-test/suite/galera/r/MDEV-22227.result
Normal file
16
mysql-test/suite/galera/r/MDEV-22227.result
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
connection node_2;
|
||||||
|
connection node_1;
|
||||||
|
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
|
||||||
|
LOCK TABLE t1 WRITE CONCURRENT;
|
||||||
|
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
|
||||||
|
connection node_1a;
|
||||||
|
SET lock_wait_timeout= 1;
|
||||||
|
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||||
|
connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1;
|
||||||
|
connection node_1b;
|
||||||
|
SET SESSION wsrep_sync_wait = 0;
|
||||||
|
connection node_1;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
connection node_1a;
|
||||||
|
DROP VIEW v1;
|
||||||
|
DROP TABLE t1;
|
26
mysql-test/suite/galera/t/MDEV-22227.test
Normal file
26
mysql-test/suite/galera/t/MDEV-22227.test
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
--source include/galera_cluster.inc
|
||||||
|
--source include/have_log_bin.inc
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
|
||||||
|
LOCK TABLE t1 WRITE CONCURRENT;
|
||||||
|
|
||||||
|
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
|
||||||
|
--connection node_1a
|
||||||
|
# TOI operations will ignore lock_wait_timeout
|
||||||
|
SET lock_wait_timeout= 1;
|
||||||
|
--send CREATE VIEW v1 AS SELECT * FROM t1
|
||||||
|
|
||||||
|
--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1
|
||||||
|
--connection node_1b
|
||||||
|
SET SESSION wsrep_sync_wait = 0;
|
||||||
|
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'Waiting for table level lock'
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
--connection node_1
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--connection node_1a
|
||||||
|
--reap
|
||||||
|
|
||||||
|
DROP VIEW v1;
|
||||||
|
DROP TABLE t1;
|
@@ -1,6 +1,5 @@
|
|||||||
GCF-336 :
|
GCF-336 :
|
||||||
GCF-582 :
|
GCF-582 :
|
||||||
GCF-609 :
|
|
||||||
GCF-810A :
|
GCF-810A :
|
||||||
GCF-810B :
|
GCF-810B :
|
||||||
GCF-810C :
|
GCF-810C :
|
||||||
|
@@ -1,20 +1,78 @@
|
|||||||
|
connection node_2;
|
||||||
|
connection node_1;
|
||||||
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
|
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
|
||||||
|
connection node_1;
|
||||||
SET SESSION wsrep_trx_fragment_size=1;
|
SET SESSION wsrep_trx_fragment_size=1;
|
||||||
SET AUTOCOMMIT=OFF;
|
SET AUTOCOMMIT=OFF;
|
||||||
START TRANSACTION;
|
START TRANSACTION;
|
||||||
INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
|
INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
|
||||||
|
connection node_2;
|
||||||
SET SESSION wsrep_trx_fragment_size=1;
|
SET SESSION wsrep_trx_fragment_size=1;
|
||||||
SET AUTOCOMMIT=OFF;
|
SET AUTOCOMMIT=OFF;
|
||||||
START TRANSACTION;
|
START TRANSACTION;
|
||||||
INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
|
INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
|
||||||
INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
|
INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
|
||||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
ERROR 23000: Duplicate entry '11' for key 'PRIMARY'
|
||||||
INSERT INTO t1 VALUES (31),(32),(33);
|
INSERT INTO t1 VALUES (31),(32),(33);
|
||||||
SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log;
|
SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log;
|
||||||
COUNT(*) = 0
|
COUNT(*) = 0
|
||||||
0
|
0
|
||||||
|
connection node_1;
|
||||||
SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log;
|
SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log;
|
||||||
COUNT(*) = 0
|
COUNT(*) = 0
|
||||||
0
|
0
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
connection node_2;
|
||||||
|
COMMIT;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
f1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
6
|
||||||
|
7
|
||||||
|
8
|
||||||
|
9
|
||||||
|
10
|
||||||
|
11
|
||||||
|
12
|
||||||
|
13
|
||||||
|
14
|
||||||
|
15
|
||||||
|
16
|
||||||
|
17
|
||||||
|
18
|
||||||
|
19
|
||||||
|
20
|
||||||
|
31
|
||||||
|
32
|
||||||
|
33
|
||||||
|
connection node_1;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
f1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
6
|
||||||
|
7
|
||||||
|
8
|
||||||
|
9
|
||||||
|
10
|
||||||
|
11
|
||||||
|
12
|
||||||
|
13
|
||||||
|
14
|
||||||
|
15
|
||||||
|
16
|
||||||
|
17
|
||||||
|
18
|
||||||
|
19
|
||||||
|
20
|
||||||
|
31
|
||||||
|
32
|
||||||
|
33
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
@@ -17,7 +17,7 @@ SET SESSION wsrep_trx_fragment_size=1;
|
|||||||
SET AUTOCOMMIT=OFF;
|
SET AUTOCOMMIT=OFF;
|
||||||
START TRANSACTION;
|
START TRANSACTION;
|
||||||
INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
|
INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
|
||||||
--error ER_LOCK_DEADLOCK
|
--error ER_DUP_ENTRY
|
||||||
INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
|
INSERT INTO t1 VALUES (11),(12),(13),(14),(15),(16),(17),(18),(19),(20);
|
||||||
INSERT INTO t1 VALUES (31),(32),(33);
|
INSERT INTO t1 VALUES (31),(32),(33);
|
||||||
|
|
||||||
@@ -27,4 +27,11 @@ SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log;
|
|||||||
SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log;
|
SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log;
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
|
--connection node_2
|
||||||
|
COMMIT;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
--connection node_1
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
@@ -1,18 +1,38 @@
|
|||||||
connection node_2;
|
connection node_2;
|
||||||
connection node_1;
|
connection node_1;
|
||||||
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(10)) ENGINE=InnoDB;
|
|
||||||
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
|
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
|
||||||
connection node_1;
|
connection node_1;
|
||||||
SET SESSION wsrep_trx_fragment_size = 1;
|
SET SESSION wsrep_trx_fragment_size = 1;
|
||||||
|
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
|
||||||
|
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY);
|
||||||
|
INSERT INTO t2 VALUES (1),(2),(3);
|
||||||
|
ALTER TABLE t2 DROP PRIMARY KEY;
|
||||||
|
INSERT INTO t2 VALUES (1);
|
||||||
|
SET SESSION wsrep_trx_fragment_size = 1;
|
||||||
|
START TRANSACTION;
|
||||||
|
INSERT INTO t1 SELECT * FROM t2;
|
||||||
|
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||||
|
SELECT * FROM t1;
|
||||||
|
f1
|
||||||
|
connection node_2;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
f1
|
||||||
|
connection node_1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
||||||
|
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(10)) ENGINE=InnoDB;
|
||||||
|
connection node_1;
|
||||||
|
SET SESSION wsrep_trx_fragment_size = 1;
|
||||||
START TRANSACTION;
|
START TRANSACTION;
|
||||||
INSERT INTO t1 VALUES (1, 'node1');
|
INSERT INTO t1 VALUES (1, 'node1');
|
||||||
connection node_1a;
|
connection node_1a;
|
||||||
INSERT INTO t1 VALUES (5, 'node2');
|
INSERT INTO t1 VALUES (5, 'node2');
|
||||||
connection node_1;
|
connection node_1;
|
||||||
INSERT INTO t1 VALUES (5, 'node1');
|
INSERT INTO t1 VALUES (5, 'node1');
|
||||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
ERROR 23000: Duplicate entry '5' for key 'PRIMARY'
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
f1 f2
|
f1 f2
|
||||||
|
1 node1
|
||||||
5 node2
|
5 node2
|
||||||
SET SESSION wsrep_trx_fragment_size = 10000;
|
SET SESSION wsrep_trx_fragment_size = 10000;
|
||||||
START TRANSACTION;
|
START TRANSACTION;
|
||||||
@@ -24,6 +44,7 @@ INSERT INTO t1 VALUES(15, 'node2');
|
|||||||
connection node_1;
|
connection node_1;
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
f1 f2
|
f1 f2
|
||||||
|
1 node1
|
||||||
5 node2
|
5 node2
|
||||||
10 node1
|
10 node1
|
||||||
INSERT INTO t1 VALUES(15, 'node1');
|
INSERT INTO t1 VALUES(15, 'node1');
|
||||||
@@ -31,6 +52,7 @@ ERROR 23000: Duplicate entry '15' for key 'PRIMARY'
|
|||||||
COMMIT;
|
COMMIT;
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
f1 f2
|
f1 f2
|
||||||
|
1 node1
|
||||||
5 node2
|
5 node2
|
||||||
10 node1
|
10 node1
|
||||||
15 node2
|
15 node2
|
||||||
|
@@ -13,7 +13,7 @@ INSERT INTO t1 VALUES (REPEAT('e', 512));
|
|||||||
INSERT INTO t1 VALUES (REPEAT('f', 512));
|
INSERT INTO t1 VALUES (REPEAT('f', 512));
|
||||||
connection node_2;
|
connection node_2;
|
||||||
connection node_1;
|
connection node_1;
|
||||||
INSERT INTO t1 VALUES (REPEAT('c', 512));
|
INSERT INTO t1 VALUES (REPEAT('g', 1024)),(REPEAT('c', 512));
|
||||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||||
connection node_1;
|
connection node_1;
|
||||||
SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log;
|
SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log;
|
||||||
|
15
mysql-test/suite/galera_sr/r/mysql-wsrep-bugs-900.result
Normal file
15
mysql-test/suite/galera_sr/r/mysql-wsrep-bugs-900.result
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
connection node_2;
|
||||||
|
connection node_1;
|
||||||
|
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
|
||||||
|
SET SESSION wsrep_trx_fragment_size=1;
|
||||||
|
START TRANSACTION;
|
||||||
|
INSERT INTO t1 VALUES (1);
|
||||||
|
SET SESSION wsrep_cluster_name = ' ';
|
||||||
|
ERROR HY000: Variable 'wsrep_cluster_name' is a GLOBAL variable and should be set with SET GLOBAL
|
||||||
|
INSERT INTO t1 VALUES (2);
|
||||||
|
COMMIT;
|
||||||
|
SELECT f1 AS expect_1_and_2 FROM t1;
|
||||||
|
expect_1_and_2
|
||||||
|
1
|
||||||
|
2
|
||||||
|
DROP TABLE t1;
|
@@ -1,15 +1,43 @@
|
|||||||
--source include/galera_cluster.inc
|
--source include/galera_cluster.inc
|
||||||
--source include/have_innodb.inc
|
--source include/have_innodb.inc
|
||||||
|
|
||||||
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(10)) ENGINE=InnoDB;
|
|
||||||
|
|
||||||
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
|
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
|
||||||
|
|
||||||
#
|
#
|
||||||
# Test 1: statement rollback is not safe
|
# Test 1: statement rollback is not safe.
|
||||||
# (some fragments were already replicated)
|
# Statement has already replicated some fragments
|
||||||
#
|
#
|
||||||
|
--connection node_1
|
||||||
|
SET SESSION wsrep_trx_fragment_size = 1;
|
||||||
|
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
|
||||||
|
CREATE TABLE t2 (f1 INTEGER PRIMARY KEY);
|
||||||
|
INSERT INTO t2 VALUES (1),(2),(3);
|
||||||
|
ALTER TABLE t2 DROP PRIMARY KEY;
|
||||||
|
INSERT INTO t2 VALUES (1);
|
||||||
|
|
||||||
|
SET SESSION wsrep_trx_fragment_size = 1;
|
||||||
|
START TRANSACTION;
|
||||||
|
|
||||||
|
# The following INSERT .. SELECT inserts a duplicate key,
|
||||||
|
# ER_LOCK_DEADLOCK is the only possible outcome at this point.
|
||||||
|
# Notice that ER_DUP_ENTRY is NOT an option here because we were
|
||||||
|
# forced to rollback the whole transaction (not just the statement)
|
||||||
|
--error ER_LOCK_DEADLOCK
|
||||||
|
INSERT INTO t1 SELECT * FROM t2;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
--connection node_2
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
--connection node_1
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test 2: statement rollback is safe.
|
||||||
|
# Fragments were already replicated, not in the same statement
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 CHAR(10)) ENGINE=InnoDB;
|
||||||
--connection node_1
|
--connection node_1
|
||||||
SET SESSION wsrep_trx_fragment_size = 1;
|
SET SESSION wsrep_trx_fragment_size = 1;
|
||||||
START TRANSACTION;
|
START TRANSACTION;
|
||||||
@@ -19,20 +47,16 @@ INSERT INTO t1 VALUES (1, 'node1');
|
|||||||
INSERT INTO t1 VALUES (5, 'node2');
|
INSERT INTO t1 VALUES (5, 'node2');
|
||||||
|
|
||||||
--connection node_1
|
--connection node_1
|
||||||
# If we try to INSERT a duplicate key, ER_LOCK_DEADLOCK is the only possible
|
# Only the statement is rolled back, expect ER_DUP_ENTRY
|
||||||
# outcome at this point. Notice that ER_DUP_ENTRY is NOT an option here
|
--error ER_DUP_ENTRY
|
||||||
# because we were forced to rollback the whole transaction (not just the
|
|
||||||
# statement)
|
|
||||||
--error ER_LOCK_DEADLOCK
|
|
||||||
INSERT INTO t1 VALUES (5, 'node1');
|
INSERT INTO t1 VALUES (5, 'node1');
|
||||||
|
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Test 2: statement rollback is safe
|
# Test 3: statement rollback is safe
|
||||||
# (no fragments have been replicated)
|
# No fragments have been replicated
|
||||||
#
|
#
|
||||||
|
|
||||||
SET SESSION wsrep_trx_fragment_size = 10000;
|
SET SESSION wsrep_trx_fragment_size = 10000;
|
||||||
|
|
||||||
START TRANSACTION;
|
START TRANSACTION;
|
||||||
|
@@ -22,12 +22,13 @@ INSERT INTO t1 VALUES (REPEAT('f', 512));
|
|||||||
--let $wait_condition = SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log;
|
--let $wait_condition = SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log;
|
||||||
|
|
||||||
--connection node_1
|
--connection node_1
|
||||||
# Deadlock error instead of dupkey since the transaction is SR and
|
# Deadlock error instead of dupkey since the transaction is SR,
|
||||||
# statement rollback is not safe.
|
# and the statement has already replicated a fragment (which
|
||||||
|
# makes statement rollback unsafe).
|
||||||
--error ER_LOCK_DEADLOCK
|
--error ER_LOCK_DEADLOCK
|
||||||
INSERT INTO t1 VALUES (REPEAT('c', 512));
|
INSERT INTO t1 VALUES (REPEAT('g', 1024)),(REPEAT('c', 512));
|
||||||
|
|
||||||
# Confirm that the wsrep_streaming_log table is now empty, as it was a full transaction rollback
|
# Confirm that the wsrep_schema table is now empty, as it was a full transaction rollback
|
||||||
|
|
||||||
--connection node_1
|
--connection node_1
|
||||||
SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log;
|
SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log;
|
||||||
|
22
mysql-test/suite/galera_sr/t/mysql-wsrep-bugs-900.test
Normal file
22
mysql-test/suite/galera_sr/t/mysql-wsrep-bugs-900.test
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#
|
||||||
|
# Statement with no side effects causes unnecessary full rollback
|
||||||
|
#
|
||||||
|
|
||||||
|
--source include/galera_cluster.inc
|
||||||
|
|
||||||
|
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
|
||||||
|
SET SESSION wsrep_trx_fragment_size=1;
|
||||||
|
START TRANSACTION;
|
||||||
|
INSERT INTO t1 VALUES (1);
|
||||||
|
# Let's cause some bogus error with a statement that
|
||||||
|
# does not cause any replication event.
|
||||||
|
# The following used to return error ER_LOCK_DEADLOCK
|
||||||
|
# and cause the entire transaction to be rolled back.
|
||||||
|
--error ER_GLOBAL_VARIABLE
|
||||||
|
SET SESSION wsrep_cluster_name = ' ';
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (2);
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
SELECT f1 AS expect_1_and_2 FROM t1;
|
||||||
|
DROP TABLE t1;
|
@@ -2890,3 +2890,30 @@ SELECT COUNT(*) FROM t1;
|
|||||||
COUNT(*)
|
COUNT(*)
|
||||||
16
|
16
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# MDEV-25630 Rollback of instant operation adds wrong
|
||||||
|
# column to secondary index
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (f1 INT, f2 INT, f3 INT, f4 INT,
|
||||||
|
PRIMARY KEY(f1, f4),
|
||||||
|
KEY(f2))ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t2 (f1 INT, f2 INT, PRIMARY KEY(f1),
|
||||||
|
FOREIGN KEY fk (f2) REFERENCES t2(f1)
|
||||||
|
)ENGINE=InnoDB;
|
||||||
|
ALTER TABLE t1 ADD f5 INT;
|
||||||
|
SET FOREIGN_KEY_CHECKS=0;
|
||||||
|
ALTER TABLE t1 DROP COLUMN f3, ADD FOREIGN KEY fk (f1)
|
||||||
|
REFERENCES x(x);
|
||||||
|
ERROR HY000: Failed to add the foreign key constraint 'test/fk' to system tables
|
||||||
|
ALTER TABLE t1 DROP COLUMN f5;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`f1` int(11) NOT NULL,
|
||||||
|
`f2` int(11) DEFAULT NULL,
|
||||||
|
`f3` int(11) DEFAULT NULL,
|
||||||
|
`f4` int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (`f1`,`f4`),
|
||||||
|
KEY `f2` (`f2`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
@@ -929,3 +929,23 @@ INSERT INTO t1(a, b) SELECT '', '' FROM seq_1_to_16;
|
|||||||
SELECT COUNT(*) FROM t1;
|
SELECT COUNT(*) FROM t1;
|
||||||
# Cleanup
|
# Cleanup
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-25630 Rollback of instant operation adds wrong
|
||||||
|
--echo # column to secondary index
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1 (f1 INT, f2 INT, f3 INT, f4 INT,
|
||||||
|
PRIMARY KEY(f1, f4),
|
||||||
|
KEY(f2))ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t2 (f1 INT, f2 INT, PRIMARY KEY(f1),
|
||||||
|
FOREIGN KEY fk (f2) REFERENCES t2(f1)
|
||||||
|
)ENGINE=InnoDB;
|
||||||
|
|
||||||
|
ALTER TABLE t1 ADD f5 INT;
|
||||||
|
SET FOREIGN_KEY_CHECKS=0;
|
||||||
|
--error ER_FK_FAIL_ADD_SYSTEM
|
||||||
|
ALTER TABLE t1 DROP COLUMN f3, ADD FOREIGN KEY fk (f1)
|
||||||
|
REFERENCES x(x);
|
||||||
|
ALTER TABLE t1 DROP COLUMN f5;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
127
mysys/thr_lock.c
127
mysys/thr_lock.c
@@ -95,24 +95,6 @@ my_bool thr_lock_inited=0;
|
|||||||
ulong locks_immediate = 0L, locks_waited = 0L;
|
ulong locks_immediate = 0L, locks_waited = 0L;
|
||||||
enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE;
|
enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE;
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
|
||||||
static wsrep_thd_is_brute_force_fun wsrep_thd_is_brute_force= NULL;
|
|
||||||
static wsrep_abort_thd_fun wsrep_abort_thd= NULL;
|
|
||||||
static my_bool wsrep_debug;
|
|
||||||
static my_bool wsrep_convert_LOCK_to_trx;
|
|
||||||
static wsrep_on_fun wsrep_on = NULL;
|
|
||||||
|
|
||||||
void wsrep_thr_lock_init(
|
|
||||||
wsrep_thd_is_brute_force_fun bf_fun, wsrep_abort_thd_fun abort_fun,
|
|
||||||
my_bool debug, my_bool convert_LOCK_to_trx, wsrep_on_fun on_fun
|
|
||||||
) {
|
|
||||||
wsrep_thd_is_brute_force = bf_fun;
|
|
||||||
wsrep_abort_thd = abort_fun;
|
|
||||||
wsrep_debug = debug;
|
|
||||||
wsrep_convert_LOCK_to_trx= convert_LOCK_to_trx;
|
|
||||||
wsrep_on = on_fun;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* The following constants are only for debug output */
|
/* The following constants are only for debug output */
|
||||||
#define MAX_THREADS 1000
|
#define MAX_THREADS 1000
|
||||||
#define MAX_LOCKS 1000
|
#define MAX_LOCKS 1000
|
||||||
@@ -653,93 +635,6 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
|
|||||||
DBUG_RETURN(result);
|
DBUG_RETURN(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
|
||||||
/*
|
|
||||||
* If brute force applier would need to wait for a thr lock,
|
|
||||||
* it needs to make sure that it will get the lock without (too much)
|
|
||||||
* delay.
|
|
||||||
* We identify here the owners of blocking locks and ask them to
|
|
||||||
* abort. We then put our lock request in the first place in the
|
|
||||||
* wait queue. When lock holders abort (one by one) the lock release
|
|
||||||
* algorithm should grant the lock to us. We rely on this and proceed
|
|
||||||
* to wait_for_locks().
|
|
||||||
* wsrep_break_locks() should be called in all the cases, where lock
|
|
||||||
* wait would happen.
|
|
||||||
*
|
|
||||||
* TODO: current implementation might not cover all possible lock wait
|
|
||||||
* situations. This needs an review still.
|
|
||||||
* TODO: lock release, might favor some other lock (instead our bf).
|
|
||||||
* This needs an condition to check for bf locks first.
|
|
||||||
* TODO: we still have a debug fprintf, this should be removed
|
|
||||||
*/
|
|
||||||
static my_bool
|
|
||||||
wsrep_break_lock(
|
|
||||||
THR_LOCK_DATA *data, struct st_lock_list *lock_queue1,
|
|
||||||
struct st_lock_list *wait_queue)
|
|
||||||
{
|
|
||||||
if (wsrep_on && wsrep_on(data->owner->mysql_thd) &&
|
|
||||||
wsrep_thd_is_brute_force &&
|
|
||||||
wsrep_thd_is_brute_force(data->owner->mysql_thd, TRUE))
|
|
||||||
{
|
|
||||||
THR_LOCK_DATA *holder;
|
|
||||||
|
|
||||||
/* if locking session conversion to transaction has been enabled,
|
|
||||||
we know that this conflicting lock must be read lock and furthermore,
|
|
||||||
lock holder is read-only. It is safe to wait for him.
|
|
||||||
*/
|
|
||||||
#ifdef TODO_WHEN_LOCK_TABLES_IS_A_TRANSACTION
|
|
||||||
if (wsrep_convert_LOCK_to_trx &&
|
|
||||||
(THD*)(data->owner->mysql_thd)->in_lock_tables)
|
|
||||||
{
|
|
||||||
if (wsrep_debug)
|
|
||||||
fprintf(stderr,"WSREP wsrep_break_lock read lock untouched\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (wsrep_debug)
|
|
||||||
fprintf(stderr,"WSREP wsrep_break_lock aborting locks\n");
|
|
||||||
|
|
||||||
/* aborting lock holder(s) here */
|
|
||||||
for (holder=(lock_queue1) ? lock_queue1->data : NULL;
|
|
||||||
holder;
|
|
||||||
holder=holder->next)
|
|
||||||
{
|
|
||||||
if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd, TRUE))
|
|
||||||
{
|
|
||||||
wsrep_abort_thd(data->owner->mysql_thd,
|
|
||||||
holder->owner->mysql_thd, FALSE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (wsrep_debug)
|
|
||||||
fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add our lock to the head of the wait queue */
|
|
||||||
if (*(wait_queue->last)==wait_queue->data)
|
|
||||||
{
|
|
||||||
wait_queue->last=&data->next;
|
|
||||||
assert(wait_queue->data==0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(wait_queue->data!=0);
|
|
||||||
wait_queue->data->prev=&data->next;
|
|
||||||
}
|
|
||||||
data->next=wait_queue->data;
|
|
||||||
data->prev=&wait_queue->data;
|
|
||||||
wait_queue->data=data;
|
|
||||||
data->cond=get_cond();
|
|
||||||
|
|
||||||
statistic_increment(locks_immediate,&THR_LOCK_lock);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static enum enum_thr_lock_result
|
static enum enum_thr_lock_result
|
||||||
thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout)
|
thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout)
|
||||||
{
|
{
|
||||||
@@ -747,9 +642,6 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout)
|
|||||||
enum enum_thr_lock_result result= THR_LOCK_SUCCESS;
|
enum enum_thr_lock_result result= THR_LOCK_SUCCESS;
|
||||||
struct st_lock_list *wait_queue;
|
struct st_lock_list *wait_queue;
|
||||||
enum thr_lock_type lock_type= data->type;
|
enum thr_lock_type lock_type= data->type;
|
||||||
#ifdef WITH_WSREP
|
|
||||||
my_bool wsrep_lock_inserted= FALSE;
|
|
||||||
#endif
|
|
||||||
MYSQL_TABLE_WAIT_VARIABLES(locker, state) /* no ';' */
|
MYSQL_TABLE_WAIT_VARIABLES(locker, state) /* no ';' */
|
||||||
DBUG_ENTER("thr_lock");
|
DBUG_ENTER("thr_lock");
|
||||||
|
|
||||||
@@ -846,13 +738,6 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout)
|
|||||||
lock but a high priority write waiting in the write_wait queue.
|
lock but a high priority write waiting in the write_wait queue.
|
||||||
In the latter case we should yield the lock to the writer.
|
In the latter case we should yield the lock to the writer.
|
||||||
*/
|
*/
|
||||||
#ifdef WITH_WSREP
|
|
||||||
if (wsrep_break_lock(data, &lock->write, &lock->read_wait))
|
|
||||||
{
|
|
||||||
wsrep_lock_inserted= TRUE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
wait_queue= &lock->read_wait;
|
wait_queue= &lock->read_wait;
|
||||||
}
|
}
|
||||||
else /* Request for WRITE lock */
|
else /* Request for WRITE lock */
|
||||||
@@ -1000,20 +885,8 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout)
|
|||||||
(ulong) lock->read.data->owner->thread_id,
|
(ulong) lock->read.data->owner->thread_id,
|
||||||
data->type));
|
data->type));
|
||||||
}
|
}
|
||||||
#ifdef WITH_WSREP
|
|
||||||
if (wsrep_break_lock(data, &lock->write, &lock->write_wait))
|
|
||||||
{
|
|
||||||
wsrep_lock_inserted= TRUE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
wait_queue= &lock->write_wait;
|
wait_queue= &lock->write_wait;
|
||||||
}
|
}
|
||||||
/* Can't get lock yet; Wait for it */
|
|
||||||
#ifdef WITH_WSREP
|
|
||||||
if (wsrep_lock_inserted && wsrep_on(data->owner->mysql_thd))
|
|
||||||
DBUG_RETURN(wait_for_lock(wait_queue, data, 1, lock_wait_timeout));
|
|
||||||
#endif
|
|
||||||
result= wait_for_lock(wait_queue, data, 0, lock_wait_timeout);
|
result= wait_for_lock(wait_queue, data, 0, lock_wait_timeout);
|
||||||
MYSQL_END_TABLE_LOCK_WAIT(locker);
|
MYSQL_END_TABLE_LOCK_WAIT(locker);
|
||||||
DBUG_RETURN(result);
|
DBUG_RETURN(result);
|
||||||
|
28
sql/log.cc
28
sql/log.cc
@@ -11079,34 +11079,6 @@ void wsrep_thd_binlog_stmt_rollback(THD * thd)
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wsrep_stmt_rollback_is_safe(THD* thd)
|
|
||||||
{
|
|
||||||
bool ret(true);
|
|
||||||
|
|
||||||
DBUG_ENTER("wsrep_binlog_stmt_rollback_is_safe");
|
|
||||||
|
|
||||||
binlog_cache_mngr *cache_mngr=
|
|
||||||
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
|
|
||||||
|
|
||||||
if (binlog_hton && cache_mngr)
|
|
||||||
{
|
|
||||||
binlog_cache_data * trx_cache = &cache_mngr->trx_cache;
|
|
||||||
if (thd->wsrep_sr().fragments_certified() > 0 &&
|
|
||||||
(trx_cache->get_prev_position() == MY_OFF_T_UNDEF ||
|
|
||||||
trx_cache->get_prev_position() < thd->wsrep_sr().log_position()))
|
|
||||||
{
|
|
||||||
WSREP_DEBUG("statement rollback is not safe for streaming replication"
|
|
||||||
" pre-stmt_pos: %llu, frag repl pos: %zu\n"
|
|
||||||
"Thread: %llu, SQL: %s",
|
|
||||||
trx_cache->get_prev_position(),
|
|
||||||
thd->wsrep_sr().log_position(),
|
|
||||||
thd->thread_id, thd->query());
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DBUG_RETURN(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wsrep_register_binlog_handler(THD *thd, bool trx)
|
void wsrep_register_binlog_handler(THD *thd, bool trx)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("register_binlog_handler");
|
DBUG_ENTER("register_binlog_handler");
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
|
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
|
||||||
Copyright (c) 2009, 2020, MariaDB Corporation.
|
Copyright (c) 2009, 2021, MariaDB Corporation.
|
||||||
|
|
||||||
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
|
||||||
@@ -664,6 +664,7 @@ typedef struct system_variables
|
|||||||
are based on the cluster size):
|
are based on the cluster size):
|
||||||
*/
|
*/
|
||||||
ulong saved_auto_increment_increment, saved_auto_increment_offset;
|
ulong saved_auto_increment_increment, saved_auto_increment_offset;
|
||||||
|
ulong saved_lock_wait_timeout;
|
||||||
ulonglong wsrep_gtid_seq_no;
|
ulonglong wsrep_gtid_seq_no;
|
||||||
#endif /* WITH_WSREP */
|
#endif /* WITH_WSREP */
|
||||||
uint eq_range_index_dive_limit;
|
uint eq_range_index_dive_limit;
|
||||||
|
@@ -941,9 +941,6 @@ void wsrep_init_startup (bool sst_first)
|
|||||||
{
|
{
|
||||||
if (wsrep_init()) unireg_abort(1);
|
if (wsrep_init()) unireg_abort(1);
|
||||||
|
|
||||||
wsrep_thr_lock_init(wsrep_thd_is_BF, wsrep_thd_bf_abort,
|
|
||||||
wsrep_debug, wsrep_convert_LOCK_to_trx, wsrep_on);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Pre-initialize global_system_variables.table_plugin with a dummy engine
|
Pre-initialize global_system_variables.table_plugin with a dummy engine
|
||||||
(placeholder) required during the initialization of wsrep threads (THDs).
|
(placeholder) required during the initialization of wsrep threads (THDs).
|
||||||
@@ -2418,6 +2415,13 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
|
|||||||
thd->variables.auto_increment_increment= 1;
|
thd->variables.auto_increment_increment= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TOI operations will ignore provided lock_wait_timeout and restore it
|
||||||
|
after operation is done.
|
||||||
|
*/
|
||||||
|
thd->variables.saved_lock_wait_timeout= thd->variables.lock_wait_timeout;
|
||||||
|
thd->variables.lock_wait_timeout= LONG_TIMEOUT;
|
||||||
|
|
||||||
if (thd->variables.wsrep_on && wsrep_thd_is_local(thd))
|
if (thd->variables.wsrep_on && wsrep_thd_is_local(thd))
|
||||||
{
|
{
|
||||||
switch (wsrep_OSU_method_get(thd)) {
|
switch (wsrep_OSU_method_get(thd)) {
|
||||||
@@ -2453,6 +2457,9 @@ void wsrep_to_isolation_end(THD *thd)
|
|||||||
{
|
{
|
||||||
DBUG_ASSERT(wsrep_thd_is_local_toi(thd) ||
|
DBUG_ASSERT(wsrep_thd_is_local_toi(thd) ||
|
||||||
wsrep_thd_is_in_rsu(thd));
|
wsrep_thd_is_in_rsu(thd));
|
||||||
|
|
||||||
|
thd->variables.lock_wait_timeout= thd->variables.saved_lock_wait_timeout;
|
||||||
|
|
||||||
if (wsrep_thd_is_local_toi(thd))
|
if (wsrep_thd_is_local_toi(thd))
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(wsrep_OSU_method_get(thd) == WSREP_OSU_TOI);
|
DBUG_ASSERT(wsrep_OSU_method_get(thd) == WSREP_OSU_TOI);
|
||||||
|
@@ -389,8 +389,6 @@ int wsrep_to_buf_helper(
|
|||||||
int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
|
int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
|
||||||
int wsrep_create_event_query(THD *thd, uchar** buf, size_t* buf_len);
|
int wsrep_create_event_query(THD *thd, uchar** buf, size_t* buf_len);
|
||||||
|
|
||||||
bool wsrep_stmt_rollback_is_safe(THD* thd);
|
|
||||||
|
|
||||||
void wsrep_init_sidno(const wsrep_uuid_t&);
|
void wsrep_init_sidno(const wsrep_uuid_t&);
|
||||||
bool wsrep_node_is_donor();
|
bool wsrep_node_is_donor();
|
||||||
bool wsrep_node_is_synced();
|
bool wsrep_node_is_synced();
|
||||||
|
@@ -374,11 +374,14 @@ static inline int wsrep_before_rollback(THD* thd, bool all)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (thd->wsrep_trx().is_streaming() &&
|
if (thd->wsrep_trx().is_streaming() &&
|
||||||
!wsrep_stmt_rollback_is_safe(thd))
|
(wsrep_fragments_certified_for_stmt(thd) > 0))
|
||||||
{
|
{
|
||||||
/* Non-safe statement rollback during SR multi statement
|
/* Non-safe statement rollback during SR multi statement
|
||||||
transasction. Self abort the transaction, the actual rollback
|
transaction. A statement rollback is considered unsafe, if
|
||||||
and error handling will be done in after statement phase. */
|
the same statement has already replicated one or more fragments.
|
||||||
|
Self abort the transaction, the actual rollback and error
|
||||||
|
handling will be done in after statement phase. */
|
||||||
|
WSREP_DEBUG("statement rollback is not safe for streaming replication");
|
||||||
wsrep_thd_self_abort(thd);
|
wsrep_thd_self_abort(thd);
|
||||||
ret= 0;
|
ret= 0;
|
||||||
}
|
}
|
||||||
|
@@ -732,6 +732,13 @@ inline void dict_table_t::rollback_instant(
|
|||||||
const ulint* col_map)
|
const ulint* col_map)
|
||||||
{
|
{
|
||||||
ut_d(dict_sys.assert_locked());
|
ut_d(dict_sys.assert_locked());
|
||||||
|
|
||||||
|
if (cols == old_cols) {
|
||||||
|
/* Alter fails before instant operation happens.
|
||||||
|
So there is no need to do rollback instant operation */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dict_index_t* index = indexes.start;
|
dict_index_t* index = indexes.start;
|
||||||
/* index->is_instant() does not necessarily hold here, because
|
/* index->is_instant() does not necessarily hold here, because
|
||||||
the table may have been emptied */
|
the table may have been emptied */
|
||||||
|
@@ -717,6 +717,10 @@ TRUNCATE TABLE ta_l;
|
|||||||
connection master_1;
|
connection master_1;
|
||||||
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
|
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
|
||||||
a b date_format(c, '%Y-%m-%d %H:%i:%s')
|
a b date_format(c, '%Y-%m-%d %H:%i:%s')
|
||||||
|
connection master_1;
|
||||||
|
create table t2345678911234567892123456789312345678941234567895123234234(id int) ENGINE=SPIDER
|
||||||
|
COMMENT='host "192.168.21.1", user "spider", password "password", database "test32738123123123"';
|
||||||
|
drop table t2345678911234567892123456789312345678941234567895123234234;
|
||||||
|
|
||||||
deinit
|
deinit
|
||||||
connection master_1;
|
connection master_1;
|
||||||
|
@@ -2677,6 +2677,11 @@ if ($USE_CHILD_GROUP2)
|
|||||||
--connection master_1
|
--connection master_1
|
||||||
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
|
SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_l ORDER BY a;
|
||||||
|
|
||||||
|
--connection master_1
|
||||||
|
create table t2345678911234567892123456789312345678941234567895123234234(id int) ENGINE=SPIDER
|
||||||
|
COMMENT='host "192.168.21.1", user "spider", password "password", database "test32738123123123"';
|
||||||
|
drop table t2345678911234567892123456789312345678941234567895123234234;
|
||||||
|
|
||||||
--echo
|
--echo
|
||||||
--echo deinit
|
--echo deinit
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
@@ -2689,6 +2694,7 @@ if ($USE_CHILD_GROUP2)
|
|||||||
--connection child2_2
|
--connection child2_2
|
||||||
DROP DATABASE IF EXISTS auto_test_remote2;
|
DROP DATABASE IF EXISTS auto_test_remote2;
|
||||||
}
|
}
|
||||||
|
|
||||||
--disable_query_log
|
--disable_query_log
|
||||||
--disable_result_log
|
--disable_result_log
|
||||||
--source test_deinit.inc
|
--source test_deinit.inc
|
||||||
|
Submodule wsrep-lib updated: a93955ddee...f271ad0c6e
Reference in New Issue
Block a user