Skip to content

Commit feb8296

Browse files
committed
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.
1 parent e66bb57 commit feb8296

File tree

3 files changed

+91
-12
lines changed

3 files changed

+91
-12
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
CREATE TABLE t1 ENGINE=InnoDB select 1 as a, 1 as b union select 2, 2;
2+
ALTER TABLE t1 add primary key(a);
3+
CREATE PROCEDURE p1()
4+
BEGIN
5+
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION rollback;
6+
WHILE 1 DO
7+
start transaction;
8+
update t1 set b=connection_id() where a=1;
9+
commit;
10+
END WHILE;
11+
END|
12+
call p1;
13+
call p1;
14+
call p1;
15+
call p1;
16+
checking error log for 'BF lock wait long' message for 10 times every 10 seconds ...
17+
drop table t1;
18+
drop procedure p1;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
--source include/galera_cluster.inc
2+
--source include/big_test.inc
3+
4+
CREATE TABLE t1 ENGINE=InnoDB select 1 as a, 1 as b union select 2, 2;
5+
ALTER TABLE t1 add primary key(a);
6+
7+
DELIMITER |;
8+
9+
CREATE PROCEDURE p1()
10+
BEGIN
11+
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION rollback;
12+
WHILE 1 DO
13+
start transaction;
14+
update t1 set b=connection_id() where a=1;
15+
commit;
16+
END WHILE;
17+
END|
18+
19+
20+
DELIMITER ;|
21+
22+
--connect node_1_p1, 127.0.0.1, root, , test, $NODE_MYPORT_1
23+
send call p1;
24+
--connect node_1_p2, 127.0.0.1, root, , test, $NODE_MYPORT_1
25+
send call p1;
26+
--connect node_2_p1, 127.0.0.1, root, , test, $NODE_MYPORT_2
27+
send call p1;
28+
--connect node_2_p2, 127.0.0.1, root, , test, $NODE_MYPORT_2
29+
send call p1;
30+
31+
connection default;
32+
let $counter=10;
33+
let $sleep_period=10;
34+
35+
echo checking error log for 'BF lock wait long' message for $counter times every $sleep_period seconds ...;
36+
while($counter > 0)
37+
{
38+
--disable_query_log
39+
--disable_result_log
40+
eval do sleep($sleep_period);
41+
--enable_query_log
42+
--enable_result_log
43+
44+
# use error 0,1 instead if want test to continue
45+
--error 1
46+
exec grep 'BF lock wait long' $MYSQLTEST_VARDIR/log/mysqld.*.err;
47+
dec $counter;
48+
}
49+
50+
drop table t1;
51+
drop procedure p1;
52+

sql/sql_parse.cc

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5041,14 +5041,19 @@ mysql_execute_command(THD *thd)
50415041
thd->print_aborted_warning(3, "RELEASE");
50425042
}
50435043
#ifdef WITH_WSREP
5044-
if (WSREP(thd) && (thd->wsrep_conflict_state != NO_CONFLICT &&
5045-
thd->wsrep_conflict_state != REPLAYING))
5046-
{
5047-
DBUG_ASSERT(thd->is_error()); // the error is already issued
5044+
if (WSREP(thd)) {
5045+
5046+
if (thd->wsrep_conflict_state == NO_CONFLICT ||
5047+
thd->wsrep_conflict_state == REPLAYING)
5048+
{
5049+
my_ok(thd);
5050+
}
5051+
} else {
5052+
#endif /* WITH_WSREP */
5053+
my_ok(thd);
5054+
#ifdef WITH_WSREP
50485055
}
5049-
else
50505056
#endif /* WITH_WSREP */
5051-
my_ok(thd);
50525057
break;
50535058
}
50545059
case SQLCOM_ROLLBACK:
@@ -5085,13 +5090,16 @@ mysql_execute_command(THD *thd)
50855090
if (tx_release)
50865091
thd->set_killed(KILL_CONNECTION);
50875092
#ifdef WITH_WSREP
5088-
if (WSREP(thd) && thd->wsrep_conflict_state != NO_CONFLICT)
5089-
{
5090-
DBUG_ASSERT(thd->is_error()); // the error is already issued
5093+
if (WSREP(thd)) {
5094+
if (thd->wsrep_conflict_state == NO_CONFLICT) {
5095+
my_ok(thd);
5096+
}
5097+
} else {
5098+
#endif /* WITH_WSREP */
5099+
my_ok(thd);
5100+
#ifdef WITH_WSREP
50915101
}
5092-
else
50935102
#endif /* WITH_WSREP */
5094-
my_ok(thd);
50955103
break;
50965104
}
50975105
case SQLCOM_RELEASE_SAVEPOINT:
@@ -5720,8 +5728,9 @@ mysql_execute_command(THD *thd)
57205728
if (thd->is_error() || (thd->variables.option_bits & OPTION_MASTER_SQL_ERROR))
57215729
trans_rollback_stmt(thd);
57225730
#ifdef WITH_WSREP
5723-
else if (thd->spcont &&
5731+
if (thd->spcont &&
57245732
(thd->wsrep_conflict_state == MUST_ABORT ||
5733+
thd->wsrep_conflict_state == ABORTED ||
57255734
thd->wsrep_conflict_state == CERT_FAILURE))
57265735
{
57275736
/*

0 commit comments

Comments
 (0)