mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +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-582 :
|
||||
GCF-609 :
|
||||
GCF-810A :
|
||||
GCF-810B :
|
||||
GCF-810C :
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
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/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;
|
||||
|
@ -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;
|
||||
|
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(*)
|
||||
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;
|
||||
|
@ -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;
|
||||
|
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;
|
||||
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);
|
||||
|
28
sql/log.cc
28
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");
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Submodule wsrep-lib updated: a93955ddee...f271ad0c6e
Reference in New Issue
Block a user