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
e66bb57267
commit
feb8296ee6
18
mysql-test/suite/galera/r/galera_bf_lock_wait.result
Normal file
18
mysql-test/suite/galera/r/galera_bf_lock_wait.result
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
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|
|
||||||
|
call p1;
|
||||||
|
call p1;
|
||||||
|
call p1;
|
||||||
|
call p1;
|
||||||
|
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;
|
||||||
|
|
@ -5041,14 +5041,19 @@ end_with_restore_list:
|
|||||||
thd->print_aborted_warning(3, "RELEASE");
|
thd->print_aborted_warning(3, "RELEASE");
|
||||||
}
|
}
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
if (WSREP(thd) && (thd->wsrep_conflict_state != NO_CONFLICT &&
|
if (WSREP(thd)) {
|
||||||
thd->wsrep_conflict_state != REPLAYING))
|
|
||||||
|
if (thd->wsrep_conflict_state == NO_CONFLICT ||
|
||||||
|
thd->wsrep_conflict_state == REPLAYING)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(thd->is_error()); // the error is already issued
|
my_ok(thd);
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
#endif /* WITH_WSREP */
|
#endif /* WITH_WSREP */
|
||||||
my_ok(thd);
|
my_ok(thd);
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
}
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SQLCOM_ROLLBACK:
|
case SQLCOM_ROLLBACK:
|
||||||
@ -5085,13 +5090,16 @@ end_with_restore_list:
|
|||||||
if (tx_release)
|
if (tx_release)
|
||||||
thd->set_killed(KILL_CONNECTION);
|
thd->set_killed(KILL_CONNECTION);
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
if (WSREP(thd) && thd->wsrep_conflict_state != NO_CONFLICT)
|
if (WSREP(thd)) {
|
||||||
{
|
if (thd->wsrep_conflict_state == NO_CONFLICT) {
|
||||||
DBUG_ASSERT(thd->is_error()); // the error is already issued
|
my_ok(thd);
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
#endif /* WITH_WSREP */
|
#endif /* WITH_WSREP */
|
||||||
my_ok(thd);
|
my_ok(thd);
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
}
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SQLCOM_RELEASE_SAVEPOINT:
|
case SQLCOM_RELEASE_SAVEPOINT:
|
||||||
@ -5720,8 +5728,9 @@ finish:
|
|||||||
if (thd->is_error() || (thd->variables.option_bits & OPTION_MASTER_SQL_ERROR))
|
if (thd->is_error() || (thd->variables.option_bits & OPTION_MASTER_SQL_ERROR))
|
||||||
trans_rollback_stmt(thd);
|
trans_rollback_stmt(thd);
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
else if (thd->spcont &&
|
if (thd->spcont &&
|
||||||
(thd->wsrep_conflict_state == MUST_ABORT ||
|
(thd->wsrep_conflict_state == MUST_ABORT ||
|
||||||
|
thd->wsrep_conflict_state == ABORTED ||
|
||||||
thd->wsrep_conflict_state == CERT_FAILURE))
|
thd->wsrep_conflict_state == CERT_FAILURE))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user