1
0
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:
Marko Mäkelä
2021-05-03 14:34:48 +03:00
23 changed files with 295 additions and 187 deletions

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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