diff options
23 files changed, 294 insertions, 186 deletions
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/mysys/thr_lock.c b/mysys/thr_lock.c index 5004428505a..168ec035e79 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 6775e797b3c..d9a271c56bd 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -11079,34 +11079,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 0dc3199040b..49a39593f6a 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 @@ -664,6 +664,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 d39646af082..a5592fc5ae6 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -941,9 +941,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). @@ -2418,6 +2415,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)) { @@ -2453,6 +2457,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 04ea633ac53..012a3b3f8be 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -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_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 dfea7fcde8c..03dd51ea0c9 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -732,6 +732,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/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 diff --git a/wsrep-lib b/wsrep-lib -Subproject a93955ddeef5989505cbb3a9f8bb12434146256 +Subproject f271ad0c6e3c647df83c1d5ec9cd26d77cef233 |