diff --git a/mysql-test/suite/encryption/r/aria_tiny.result b/mysql-test/suite/encryption/r/aria_tiny.result index 7ad69878215..28f762255c4 100644 --- a/mysql-test/suite/encryption/r/aria_tiny.result +++ b/mysql-test/suite/encryption/r/aria_tiny.result @@ -1,4 +1,5 @@ -set global aria_encrypt_tables = 1; +SET @aria_encrypt= @@aria_encrypt_tables; +SET global aria_encrypt_tables=1; create table t1 (i int, key(i)) engine=aria; insert into t1 values (1); drop table t1; @@ -10,4 +11,17 @@ check table t1; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; -set global aria_encrypt_tables = 0; +# +# MDEV CHECK on encrypted Aria table complains about "Wrong LSN" +# +CREATE TABLE t1 (f DATE PRIMARY KEY) ENGINE=Aria; +INSERT INTO t1 (f) VALUES ('1995-01-01'),('2000-01-01'); +DELETE FROM t1 WHERE f = '2000-01-01'; +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +set global aria_encrypt_tables=@aria_encrypt; diff --git a/mysql-test/suite/encryption/t/aria_tiny.test b/mysql-test/suite/encryption/t/aria_tiny.test index a7faba9633a..337720eec52 100644 --- a/mysql-test/suite/encryption/t/aria_tiny.test +++ b/mysql-test/suite/encryption/t/aria_tiny.test @@ -1,10 +1,12 @@ --source include/have_file_key_management_plugin.inc --source include/have_sequence.inc +SET @aria_encrypt= @@aria_encrypt_tables; +SET global aria_encrypt_tables=1; # # MDEV-8022 Assertion `rc == 0' failed in ma_encrypt on dropping an encrypted Aria table # -set global aria_encrypt_tables = 1; + create table t1 (i int, key(i)) engine=aria; insert into t1 values (1); drop table t1; @@ -24,7 +26,18 @@ alter table t1 enable keys; check table t1; drop table t1; +--echo # +--echo # MDEV CHECK on encrypted Aria table complains about "Wrong LSN" +--echo # + +CREATE TABLE t1 (f DATE PRIMARY KEY) ENGINE=Aria; +INSERT INTO t1 (f) VALUES ('1995-01-01'),('2000-01-01'); +DELETE FROM t1 WHERE f = '2000-01-01'; +OPTIMIZE TABLE t1; +CHECK TABLE t1 EXTENDED; +DROP TABLE t1; + # # Cleanup # -set global aria_encrypt_tables = 0; +set global aria_encrypt_tables=@aria_encrypt; diff --git a/mysql-test/suite/galera/r/MDEV-22227.result b/mysql-test/suite/galera/r/MDEV-22227.result new file mode 100644 index 00000000000..d5afc974555 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-22227.result @@ -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; diff --git a/mysql-test/suite/galera/t/MDEV-22227.test b/mysql-test/suite/galera/t/MDEV-22227.test new file mode 100644 index 00000000000..0ee75b979e2 --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-22227.test @@ -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; diff --git a/mysql-test/suite/galera_3nodes_sr/disabled.def b/mysql-test/suite/galera_3nodes_sr/disabled.def index 0944abd0ad5..900b27860a5 100644 --- a/mysql-test/suite/galera_3nodes_sr/disabled.def +++ b/mysql-test/suite/galera_3nodes_sr/disabled.def @@ -1,6 +1,5 @@ GCF-336 : GCF-582 : -GCF-609 : GCF-810A : GCF-810B : GCF-810C : diff --git a/mysql-test/suite/galera_3nodes_sr/r/GCF-609.result b/mysql-test/suite/galera_3nodes_sr/r/GCF-609.result index 8fe13c7e2bf..db7da93c8c0 100644 --- a/mysql-test/suite/galera_3nodes_sr/r/GCF-609.result +++ b/mysql-test/suite/galera_3nodes_sr/r/GCF-609.result @@ -1,20 +1,78 @@ +connection node_2; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +connection node_1; SET SESSION wsrep_trx_fragment_size=1; SET AUTOCOMMIT=OFF; START TRANSACTION; 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 AUTOCOMMIT=OFF; 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 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); SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; COUNT(*) = 0 0 +connection node_1; SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; COUNT(*) = 0 0 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; diff --git a/mysql-test/suite/galera_3nodes_sr/t/GCF-609.test b/mysql-test/suite/galera_3nodes_sr/t/GCF-609.test index fd346cf365b..210b100a9f8 100644 --- a/mysql-test/suite/galera_3nodes_sr/t/GCF-609.test +++ b/mysql-test/suite/galera_3nodes_sr/t/GCF-609.test @@ -17,7 +17,7 @@ SET SESSION wsrep_trx_fragment_size=1; SET AUTOCOMMIT=OFF; START TRANSACTION; 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 (31),(32),(33); @@ -27,4 +27,11 @@ SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; COMMIT; +--connection node_2 +COMMIT; +SELECT * FROM t1; + +--connection node_1 +SELECT * FROM t1; + DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/GCF-572.result b/mysql-test/suite/galera_sr/r/GCF-572.result index cb4d48b3600..41ae2378a3f 100644 --- a/mysql-test/suite/galera_sr/r/GCF-572.result +++ b/mysql-test/suite/galera_sr/r/GCF-572.result @@ -1,18 +1,38 @@ connection node_2; 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; 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; +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; INSERT INTO t1 VALUES (1, 'node1'); connection node_1a; INSERT INTO t1 VALUES (5, 'node2'); connection node_1; 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; f1 f2 +1 node1 5 node2 SET SESSION wsrep_trx_fragment_size = 10000; START TRANSACTION; @@ -24,6 +44,7 @@ INSERT INTO t1 VALUES(15, 'node2'); connection node_1; SELECT * FROM t1; f1 f2 +1 node1 5 node2 10 node1 INSERT INTO t1 VALUES(15, 'node1'); @@ -31,6 +52,7 @@ ERROR 23000: Duplicate entry '15' for key 'PRIMARY' COMMIT; SELECT * FROM t1; f1 f2 +1 node1 5 node2 10 node1 15 node2 diff --git a/mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result b/mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result index b23b934da33..ad843c7c2c6 100644 --- a/mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result +++ b/mysql-test/suite/galera_sr/r/galera_sr_dupkey_error.result @@ -13,7 +13,7 @@ INSERT INTO t1 VALUES (REPEAT('e', 512)); INSERT INTO t1 VALUES (REPEAT('f', 512)); connection node_2; 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 connection node_1; SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; diff --git a/mysql-test/suite/galera_sr/r/mysql-wsrep-bugs-900.result b/mysql-test/suite/galera_sr/r/mysql-wsrep-bugs-900.result new file mode 100644 index 00000000000..a51b5299aa2 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/mysql-wsrep-bugs-900.result @@ -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; diff --git a/mysql-test/suite/galera_sr/t/GCF-572.test b/mysql-test/suite/galera_sr/t/GCF-572.test index abefb9b08f6..be77451a332 100644 --- a/mysql-test/suite/galera_sr/t/GCF-572.test +++ b/mysql-test/suite/galera_sr/t/GCF-572.test @@ -1,15 +1,43 @@ --source include/galera_cluster.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 # -# Test 1: statement rollback is not safe -# (some fragments were already replicated) +# Test 1: statement rollback is not safe. +# 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 SET SESSION wsrep_trx_fragment_size = 1; START TRANSACTION; @@ -19,20 +47,16 @@ INSERT INTO t1 VALUES (1, 'node1'); INSERT INTO t1 VALUES (5, 'node2'); --connection node_1 -# If we try to INSERT 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 +# Only the statement is rolled back, expect ER_DUP_ENTRY +--error ER_DUP_ENTRY INSERT INTO t1 VALUES (5, 'node1'); SELECT * FROM t1; # -# Test 2: statement rollback is safe -# (no fragments have been replicated) +# Test 3: statement rollback is safe +# No fragments have been replicated # - SET SESSION wsrep_trx_fragment_size = 10000; START TRANSACTION; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test b/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test index a7aca042829..146da425d88 100644 --- a/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test +++ b/mysql-test/suite/galera_sr/t/galera_sr_dupkey_error.test @@ -22,12 +22,13 @@ INSERT INTO t1 VALUES (REPEAT('f', 512)); --let $wait_condition = SELECT COUNT(*) > 0 FROM mysql.wsrep_streaming_log; --connection node_1 -# Deadlock error instead of dupkey since the transaction is SR and -# statement rollback is not safe. +# Deadlock error instead of dupkey since the transaction is SR, +# and the statement has already replicated a fragment (which +# makes statement rollback unsafe). --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 SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log; diff --git a/mysql-test/suite/galera_sr/t/mysql-wsrep-bugs-900.test b/mysql-test/suite/galera_sr/t/mysql-wsrep-bugs-900.test new file mode 100644 index 00000000000..d534fcc5524 --- /dev/null +++ b/mysql-test/suite/galera_sr/t/mysql-wsrep-bugs-900.test @@ -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; \ No newline at end of file diff --git a/mysql-test/suite/innodb/r/instant_alter.result b/mysql-test/suite/innodb/r/instant_alter.result index dad7ad6a8b0..c27ce0aeff1 100644 --- a/mysql-test/suite/innodb/r/instant_alter.result +++ b/mysql-test/suite/innodb/r/instant_alter.result @@ -2890,3 +2890,30 @@ SELECT COUNT(*) FROM t1; COUNT(*) 16 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; diff --git a/mysql-test/suite/innodb/t/instant_alter.test b/mysql-test/suite/innodb/t/instant_alter.test index b6841ddafd1..22815798f69 100644 --- a/mysql-test/suite/innodb/t/instant_alter.test +++ b/mysql-test/suite/innodb/t/instant_alter.test @@ -929,3 +929,23 @@ INSERT INTO t1(a, b) SELECT '', '' FROM seq_1_to_16; SELECT COUNT(*) FROM t1; # Cleanup 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; diff --git a/mysql-test/suite/wsrep/r/variables.result b/mysql-test/suite/wsrep/r/variables.result index 97fabd58de6..f27114989a5 100644 --- a/mysql-test/suite/wsrep/r/variables.result +++ b/mysql-test/suite/wsrep/r/variables.result @@ -166,10 +166,10 @@ wsrep_thread_count 2 # variables SELECT COUNT(*) AS EXPECT_49 FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep%"; EXPECT_49 -49 +52 SELECT COUNT(*) AS EXPECT_49 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep%"; EXPECT_49 -49 +51 SELECT VARIABLE_NAME FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE "wsrep%" ORDER BY VARIABLE_NAME; VARIABLE_NAME WSREP_AUTO_INCREMENT_CONTROL @@ -188,11 +188,13 @@ WSREP_DRUPAL_282555_WORKAROUND WSREP_FORCED_BINLOG_FORMAT WSREP_GTID_DOMAIN_ID WSREP_GTID_MODE +WSREP_GTID_SEQ_NO WSREP_IGNORE_APPLY_ERRORS WSREP_LOAD_DATA_SPLITTING WSREP_LOG_CONFLICTS WSREP_MAX_WS_ROWS WSREP_MAX_WS_SIZE +WSREP_MODE WSREP_MYSQL_REPLICATION_BUNDLE WSREP_NODE_ADDRESS WSREP_NODE_INCOMING_ADDRESS @@ -218,6 +220,7 @@ WSREP_SST_DONOR_REJECTS_QUERIES WSREP_SST_METHOD WSREP_SST_RECEIVE_ADDRESS WSREP_START_POSITION +WSREP_STRICT_DDL WSREP_SYNC_WAIT WSREP_TRX_FRAGMENT_SIZE WSREP_TRX_FRAGMENT_UNIT @@ -244,6 +247,7 @@ WSREP_LOAD_DATA_SPLITTING WSREP_LOG_CONFLICTS WSREP_MAX_WS_ROWS WSREP_MAX_WS_SIZE +WSREP_MODE WSREP_MYSQL_REPLICATION_BUNDLE WSREP_NODE_ADDRESS WSREP_NODE_INCOMING_ADDRESS @@ -269,6 +273,7 @@ WSREP_SST_DONOR_REJECTS_QUERIES WSREP_SST_METHOD WSREP_SST_RECEIVE_ADDRESS WSREP_START_POSITION +WSREP_STRICT_DDL WSREP_SYNC_WAIT WSREP_TRX_FRAGMENT_SIZE WSREP_TRX_FRAGMENT_UNIT diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index fe9ecbf22f9..c1ec062309b 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -95,24 +95,6 @@ my_bool thr_lock_inited=0; ulong locks_immediate = 0L, locks_waited = 0L; 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 */ #define MAX_THREADS 1000 #define MAX_LOCKS 1000 @@ -653,93 +635,6 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, 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 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; struct st_lock_list *wait_queue; 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 ';' */ 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. 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; } 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, 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; } - /* 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); MYSQL_END_TABLE_LOCK_WAIT(locker); DBUG_RETURN(result); diff --git a/sql/log.cc b/sql/log.cc index d2ef14863a7..df21b29e65d 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -11078,34 +11078,6 @@ void wsrep_thd_binlog_stmt_rollback(THD * thd) 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) { DBUG_ENTER("register_binlog_handler"); diff --git a/sql/sql_class.h b/sql/sql_class.h index a2dabd5e8ba..99811c9cf81 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1,6 +1,6 @@ /* 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 it under the terms of the GNU General Public License as published by @@ -688,6 +688,7 @@ typedef struct system_variables are based on the cluster size): */ ulong saved_auto_increment_increment, saved_auto_increment_offset; + ulong saved_lock_wait_timeout; ulonglong wsrep_gtid_seq_no; #endif /* WITH_WSREP */ uint eq_range_index_dive_limit; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 1618a8b6d50..6877b7c1a4d 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -943,9 +943,6 @@ void wsrep_init_startup (bool sst_first) { 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 (placeholder) required during the initialization of wsrep threads (THDs). @@ -2754,6 +2751,13 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, 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)) { switch (wsrep_OSU_method_get(thd)) { @@ -2789,6 +2793,9 @@ void wsrep_to_isolation_end(THD *thd) { DBUG_ASSERT(wsrep_thd_is_local_toi(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)) { DBUG_ASSERT(wsrep_OSU_method_get(thd) == WSREP_OSU_TOI); diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 0541f2b02ad..082a65bbad8 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -404,8 +404,6 @@ int wsrep_to_buf_helper( 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); -bool wsrep_stmt_rollback_is_safe(THD* thd); - void wsrep_init_sidno(const wsrep_uuid_t&); bool wsrep_node_is_donor(); bool wsrep_node_is_synced(); diff --git a/sql/wsrep_trans_observer.h b/sql/wsrep_trans_observer.h index d79bfa0b39b..e3e076631c7 100644 --- a/sql/wsrep_trans_observer.h +++ b/sql/wsrep_trans_observer.h @@ -374,11 +374,14 @@ static inline int wsrep_before_rollback(THD* thd, bool all) } 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 - transasction. Self abort the transaction, the actual rollback - and error handling will be done in after statement phase. */ + transaction. A statement rollback is considered unsafe, if + 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); ret= 0; } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 298f8347053..70939618c96 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -733,6 +733,13 @@ inline void dict_table_t::rollback_instant( const ulint* col_map) { 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; /* index->is_instant() does not necessarily hold here, because the table may have been emptied */ diff --git a/storage/maria/ma_close.c b/storage/maria/ma_close.c index d2bbdd6f60a..7441e29a97b 100644 --- a/storage/maria/ma_close.c +++ b/storage/maria/ma_close.c @@ -179,7 +179,8 @@ int maria_close(register MARIA_HA *info) mysql_rwlock_destroy(&share->keyinfo[i].root_lock); } } - DBUG_ASSERT(share->now_transactional == share->base.born_transactional); + DBUG_ASSERT(share->now_transactional == share->base.born_transactional || + share->internal_table); /* We assign -1 because checkpoint does not need to flush (in case we have concurrent checkpoint if no then we do not need it here also) diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 489b15490d5..b82e02bb5dc 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -187,9 +187,9 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, maria_delay_key_write) share->delay_key_write=1; - if (!share->base.born_transactional) /* For transactional ones ... */ + if (!share->now_transactional) /* If not transctional table */ { - /* ... force crash if no trn given */ + /* Pagecache requires access to info->trn->rec_lsn */ _ma_set_tmp_trn_for_table(&info, &dummy_transaction_object); info.state= &share->state.state; /* Change global values by default */ } @@ -282,7 +282,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, ulong *nulls_per_key_part; my_off_t key_root[HA_MAX_POSSIBLE_KEY]; ulonglong max_key_file_length, max_data_file_length; - my_bool versioning= 1; + my_bool versioning= 1, born_transactional; File data_file= -1, kfile= -1; struct ms3_st *s3_client= 0; S3_INFO *share_s3= 0; @@ -526,6 +526,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, file_version= (share->state.header.not_used == 0); if (file_version == 0) share->base.language= share->state.header.not_used; + born_transactional= share->base.born_transactional; share->state.state_length=base_pos; /* For newly opened tables we reset the error-has-been-printed flag */ @@ -560,7 +561,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, We can ignore testing uuid if STATE_NOT_MOVABLE is not set, as in this case the uuid will be set in _ma_mark_file_changed(). */ - if (share->base.born_transactional && + if (born_transactional && ((share->state.create_trid > trnman_get_max_trid() && !maria_in_recovery) || ((share->state.changed & STATE_NOT_MOVABLE) && @@ -601,7 +602,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, } /* Ensure we have space in the key buffer for transaction id's */ - if (share->base.born_transactional) + if (born_transactional) share->base.max_key_length= ALIGN_SIZE(share->base.max_key_length + MARIA_MAX_PACK_TRANSID_SIZE); @@ -700,7 +701,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, share->block_size= share->base.block_size; /* Convenience */ share->max_index_block_size= share->block_size - KEYPAGE_CHECKSUM_SIZE; - share->keypage_header= ((share->base.born_transactional ? + share->keypage_header= ((born_transactional ? LSN_STORE_SIZE + TRANSID_SIZE : 0) + KEYPAGE_KEYID_SIZE + KEYPAGE_FLAG_SIZE + KEYPAGE_USED_SIZE); @@ -723,7 +724,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, /* Calculate length to store a key + nod flag and transaction info */ keyinfo->max_store_length= (keyinfo->maxlength + share->base.key_reflength); - if (share->base.born_transactional) + if (born_transactional) keyinfo->max_store_length+= MARIA_INDEX_OVERHEAD_SIZE; /* See ma_delete.cc::underflow() */ @@ -862,9 +863,9 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, file for REPAIR. Don't do logging. This base information will not go to disk. */ - share->base.born_transactional= FALSE; + born_transactional= FALSE; } - if (share->base.born_transactional) + if (born_transactional) { share->page_type= PAGECACHE_LSN_PAGE; if (share->state.create_rename_lsn == LSN_NEEDS_NEW_STATE_LSNS) @@ -915,7 +916,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags, } else share->page_type= PAGECACHE_PLAIN_PAGE; - share->now_transactional= share->base.born_transactional; + share->now_transactional= born_transactional; /* Use pack_reclength as we don't want to modify base.pack_recklength */ if (share->state.header.org_data_file_type == DYNAMIC_RECORD) diff --git a/storage/spider/mysql-test/spider/r/basic_sql.result b/storage/spider/mysql-test/spider/r/basic_sql.result index 94a09fc317b..ba904b5f577 100644 --- a/storage/spider/mysql-test/spider/r/basic_sql.result +++ b/storage/spider/mysql-test/spider/r/basic_sql.result @@ -717,6 +717,10 @@ TRUNCATE TABLE ta_l; connection master_1; 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') +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 connection master_1; diff --git a/storage/spider/mysql-test/spider/t/basic_sql.test b/storage/spider/mysql-test/spider/t/basic_sql.test index 5bb040047fc..a3184a14beb 100644 --- a/storage/spider/mysql-test/spider/t/basic_sql.test +++ b/storage/spider/mysql-test/spider/t/basic_sql.test @@ -2677,6 +2677,11 @@ if ($USE_CHILD_GROUP2) --connection master_1 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 deinit --disable_warnings @@ -2689,6 +2694,7 @@ if ($USE_CHILD_GROUP2) --connection child2_2 DROP DATABASE IF EXISTS auto_test_remote2; } + --disable_query_log --disable_result_log --source test_deinit.inc