Commit 507030c4 authored by mkaruza's avatar mkaruza Committed by Jan Lindström

MDEV-27713 Crash after a conflict of applier thread with stored procedure call by event scheduler

When thread is BF aborted by high priority service, ULL (user level
locks need to be removed and released). Calling directly release of lock for
MDL_EXPLICIT type doesn't clear also `thd->ull_hash`. Method
`mysql_ull_cleanup` will properly clear all information about ULL locks
for thread.
Reviewed-by: default avatarJan Lindström <jan.lindstrom@mariadb.com>
parent 304f75c9
connection node_2;
connection node_1;
CREATE TABLE t1 (
f1 INT,
f2 VARCHAR(255) PRIMARY KEY
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO t1 VALUES(1, 'abc');
connection node_1;
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES (2,'def');
connection node_2;
SET GLOBAL event_scheduler=ON;
CREATE PROCEDURE update_table()
BEGIN
SET AUTOCOMMIT=OFF;
DO GET_LOCK('local_lock', 0);
SET DEBUG_SYNC = 'innodb_row_update_for_mysql_begin SIGNAL blocked WAIT_FOR continue';
UPDATE t1 SET f2 = 'jkl' WHERE f1 != 2;
DO RELEASE_LOCK('local_lock');
END|
CREATE DEFINER=current_user
EVENT event
ON SCHEDULE AT CURRENT_TIMESTAMP
ON COMPLETION PRESERVE
ENABLE
DO CALL update_table();
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
SET DEBUG_SYNC = 'now WAIT_FOR blocked';
connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2;
SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb";
connection node_1;
COMMIT;
connection node_2b;
SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached";
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
connection node_2a;
SET DEBUG_SYNC = 'now SIGNAL continue';
connection node_2;
SET GLOBAL event_scheduler=default;
DROP PROCEDURE update_table;
DROP EVENT event;
SET DEBUG_SYNC='reset';
SET GLOBAL debug_dbug = DEFAULT;
connection node_1;
DROP TABLE t1;
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug.inc
--source include/have_debug_sync.inc
--source include/big_test.inc
CREATE TABLE t1 (
f1 INT,
f2 VARCHAR(255) PRIMARY KEY
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO t1 VALUES(1, 'abc');
--connection node_1
SET AUTOCOMMIT=OFF;
START TRANSACTION;
INSERT INTO t1 VALUES (2,'def');
--connection node_2
SET GLOBAL event_scheduler=ON;
DELIMITER |;
CREATE PROCEDURE update_table()
BEGIN
SET AUTOCOMMIT=OFF;
DO GET_LOCK('local_lock', 0);
SET DEBUG_SYNC = 'innodb_row_update_for_mysql_begin SIGNAL blocked WAIT_FOR continue';
UPDATE t1 SET f2 = 'jkl' WHERE f1 != 2;
DO RELEASE_LOCK('local_lock');
END|
DELIMITER ;|
CREATE DEFINER=current_user
EVENT event
ON SCHEDULE AT CURRENT_TIMESTAMP
ON COMPLETION PRESERVE
ENABLE
DO CALL update_table();
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
SET DEBUG_SYNC = 'now WAIT_FOR blocked';
# Applier control thread
--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2
SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb";
--connection node_1
COMMIT;
# Applier control thread
--connection node_2b
SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached";
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
--connection node_2a
SET DEBUG_SYNC = 'now SIGNAL continue';
--connection node_2
SET GLOBAL event_scheduler=default;
DROP PROCEDURE update_table;
DROP EVENT event;
SET DEBUG_SYNC='reset';
SET GLOBAL debug_dbug = DEFAULT;
--connection node_1
DROP TABLE t1;
...@@ -342,6 +342,7 @@ int Wsrep_client_service::bf_rollback() ...@@ -342,6 +342,7 @@ int Wsrep_client_service::bf_rollback()
m_thd->global_read_lock.unlock_global_read_lock(m_thd); m_thd->global_read_lock.unlock_global_read_lock(m_thd);
} }
m_thd->release_transactional_locks(); m_thd->release_transactional_locks();
mysql_ull_cleanup(m_thd);
m_thd->mdl_context.release_explicit_locks(); m_thd->mdl_context.release_explicit_locks();
DBUG_RETURN(ret); DBUG_RETURN(ret);
......
...@@ -356,6 +356,7 @@ int Wsrep_high_priority_service::rollback(const wsrep::ws_handle& ws_handle, ...@@ -356,6 +356,7 @@ int Wsrep_high_priority_service::rollback(const wsrep::ws_handle& ws_handle,
m_thd->wsrep_cs().prepare_for_ordering(ws_handle, ws_meta, false); m_thd->wsrep_cs().prepare_for_ordering(ws_handle, ws_meta, false);
int ret= (trans_rollback_stmt(m_thd) || trans_rollback(m_thd)); int ret= (trans_rollback_stmt(m_thd) || trans_rollback(m_thd));
m_thd->release_transactional_locks(); m_thd->release_transactional_locks();
mysql_ull_cleanup(m_thd);
m_thd->mdl_context.release_explicit_locks(); m_thd->mdl_context.release_explicit_locks();
free_root(m_thd->mem_root, MYF(MY_KEEP_PREALLOC)); free_root(m_thd->mem_root, MYF(MY_KEEP_PREALLOC));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment