MDEV-14401: Stored procedure that declares a handler that catches ER_LOCK_DEADLOCK error causes thd->is_error() assertion
This was missing bug fix from MySQL wsrep i.e. Galera. Problem was that if stored procedure declares a handler that catches deadlock error, then the error may have been cleared in method sp_rcontext::handle_sql_condition(). Use wsrep_conflict_state correctly to determine is the error already sent to client. Add test case for both this bug and MDEV-12837: WSREP: BF lock wait long. Test requires both fixes to pass.
This commit is contained in:
parent
da3a3a68df
commit
ba576c5b78
23
mysql-test/suite/galera/r/galera_bf_lock_wait.result
Normal file
23
mysql-test/suite/galera/r/galera_bf_lock_wait.result
Normal file
@ -0,0 +1,23 @@
|
||||
CREATE TABLE t1 ENGINE=InnoDB select 1 as a, 1 as b union select 2, 2;
|
||||
ALTER TABLE t1 add primary key(a);
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION rollback;
|
||||
WHILE 1 DO
|
||||
start transaction;
|
||||
update t1 set b=connection_id() where a=1;
|
||||
commit;
|
||||
END WHILE;
|
||||
END|
|
||||
connect node_1_p1, 127.0.0.1, root, , test, $NODE_MYPORT_1;
|
||||
call p1;
|
||||
connect node_1_p2, 127.0.0.1, root, , test, $NODE_MYPORT_1;
|
||||
call p1;
|
||||
connect node_2_p1, 127.0.0.1, root, , test, $NODE_MYPORT_2;
|
||||
call p1;
|
||||
connect node_2_p2, 127.0.0.1, root, , test, $NODE_MYPORT_2;
|
||||
call p1;
|
||||
connection default;
|
||||
checking error log for 'BF lock wait long' message for 10 times every 10 seconds ...
|
||||
drop table t1;
|
||||
drop procedure p1;
|
52
mysql-test/suite/galera/t/galera_bf_lock_wait.test
Normal file
52
mysql-test/suite/galera/t/galera_bf_lock_wait.test
Normal file
@ -0,0 +1,52 @@
|
||||
--source include/galera_cluster.inc
|
||||
--source include/big_test.inc
|
||||
|
||||
CREATE TABLE t1 ENGINE=InnoDB select 1 as a, 1 as b union select 2, 2;
|
||||
ALTER TABLE t1 add primary key(a);
|
||||
|
||||
DELIMITER |;
|
||||
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION rollback;
|
||||
WHILE 1 DO
|
||||
start transaction;
|
||||
update t1 set b=connection_id() where a=1;
|
||||
commit;
|
||||
END WHILE;
|
||||
END|
|
||||
|
||||
|
||||
DELIMITER ;|
|
||||
|
||||
--connect node_1_p1, 127.0.0.1, root, , test, $NODE_MYPORT_1
|
||||
send call p1;
|
||||
--connect node_1_p2, 127.0.0.1, root, , test, $NODE_MYPORT_1
|
||||
send call p1;
|
||||
--connect node_2_p1, 127.0.0.1, root, , test, $NODE_MYPORT_2
|
||||
send call p1;
|
||||
--connect node_2_p2, 127.0.0.1, root, , test, $NODE_MYPORT_2
|
||||
send call p1;
|
||||
|
||||
connection default;
|
||||
let $counter=10;
|
||||
let $sleep_period=10;
|
||||
|
||||
echo checking error log for 'BF lock wait long' message for $counter times every $sleep_period seconds ...;
|
||||
while($counter > 0)
|
||||
{
|
||||
--disable_query_log
|
||||
--disable_result_log
|
||||
eval do sleep($sleep_period);
|
||||
--enable_query_log
|
||||
--enable_result_log
|
||||
|
||||
# use error 0,1 instead if want test to continue
|
||||
--error 1
|
||||
exec grep 'BF lock wait long' $MYSQLTEST_VARDIR/log/mysqld.*.err;
|
||||
dec $counter;
|
||||
}
|
||||
|
||||
drop table t1;
|
||||
drop procedure p1;
|
||||
|
@ -5563,14 +5563,19 @@ end_with_restore_list:
|
||||
thd->print_aborted_warning(3, "RELEASE");
|
||||
}
|
||||
#ifdef WITH_WSREP
|
||||
if (WSREP(thd) && (thd->wsrep_conflict_state != NO_CONFLICT &&
|
||||
thd->wsrep_conflict_state != REPLAYING))
|
||||
{
|
||||
DBUG_ASSERT(thd->is_error()); // the error is already issued
|
||||
}
|
||||
else
|
||||
if (WSREP(thd)) {
|
||||
|
||||
if (thd->wsrep_conflict_state == NO_CONFLICT ||
|
||||
thd->wsrep_conflict_state == REPLAYING)
|
||||
{
|
||||
my_ok(thd);
|
||||
}
|
||||
} else {
|
||||
#endif /* WITH_WSREP */
|
||||
my_ok(thd);
|
||||
#ifdef WITH_WSREP
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
my_ok(thd);
|
||||
break;
|
||||
}
|
||||
case SQLCOM_ROLLBACK:
|
||||
@ -5607,13 +5612,16 @@ end_with_restore_list:
|
||||
if (tx_release)
|
||||
thd->set_killed(KILL_CONNECTION);
|
||||
#ifdef WITH_WSREP
|
||||
if (WSREP(thd) && thd->wsrep_conflict_state != NO_CONFLICT)
|
||||
{
|
||||
DBUG_ASSERT(thd->is_error()); // the error is already issued
|
||||
}
|
||||
else
|
||||
if (WSREP(thd)) {
|
||||
if (thd->wsrep_conflict_state == NO_CONFLICT) {
|
||||
my_ok(thd);
|
||||
}
|
||||
} else {
|
||||
#endif /* WITH_WSREP */
|
||||
my_ok(thd);
|
||||
#ifdef WITH_WSREP
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
my_ok(thd);
|
||||
break;
|
||||
}
|
||||
case SQLCOM_RELEASE_SAVEPOINT:
|
||||
@ -6237,8 +6245,9 @@ finish:
|
||||
if (thd->is_error() || (thd->variables.option_bits & OPTION_MASTER_SQL_ERROR))
|
||||
trans_rollback_stmt(thd);
|
||||
#ifdef WITH_WSREP
|
||||
else if (thd->spcont &&
|
||||
if (thd->spcont &&
|
||||
(thd->wsrep_conflict_state == MUST_ABORT ||
|
||||
thd->wsrep_conflict_state == ABORTED ||
|
||||
thd->wsrep_conflict_state == CERT_FAILURE))
|
||||
{
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user