summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormkaruza <mario.karuza@galeracluster.com>2022-03-07 10:48:24 +0100
committerJan Lindström <jan.lindstrom@mariadb.com>2022-03-18 08:30:26 +0200
commit507030c492c17e4d1e1d3a1c8f68437b1fd8fb09 (patch)
tree9ec66b7a875901fac77825c73e7d9ba95c4e4d75
parent304f75c97311a1b746d9bb6bc94de415b5daa21c (diff)
downloadmariadb-git-507030c492c17e4d1e1d3a1c8f68437b1fd8fb09.tar.gz
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: Jan Lindström <jan.lindstrom@mariadb.com>
-rw-r--r--mysql-test/suite/galera/r/MDEV-27713.result46
-rw-r--r--mysql-test/suite/galera/t/MDEV-27713.test67
-rw-r--r--sql/wsrep_client_service.cc1
-rw-r--r--sql/wsrep_high_priority_service.cc1
4 files changed, 115 insertions, 0 deletions
diff --git a/mysql-test/suite/galera/r/MDEV-27713.result b/mysql-test/suite/galera/r/MDEV-27713.result
new file mode 100644
index 00000000000..14575cb484d
--- /dev/null
+++ b/mysql-test/suite/galera/r/MDEV-27713.result
@@ -0,0 +1,46 @@
+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;
diff --git a/mysql-test/suite/galera/t/MDEV-27713.test b/mysql-test/suite/galera/t/MDEV-27713.test
new file mode 100644
index 00000000000..4bfcd7e3d50
--- /dev/null
+++ b/mysql-test/suite/galera/t/MDEV-27713.test
@@ -0,0 +1,67 @@
+--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;
diff --git a/sql/wsrep_client_service.cc b/sql/wsrep_client_service.cc
index 8473489d2e1..464296ea6cf 100644
--- a/sql/wsrep_client_service.cc
+++ b/sql/wsrep_client_service.cc
@@ -342,6 +342,7 @@ int Wsrep_client_service::bf_rollback()
m_thd->global_read_lock.unlock_global_read_lock(m_thd);
}
m_thd->release_transactional_locks();
+ mysql_ull_cleanup(m_thd);
m_thd->mdl_context.release_explicit_locks();
DBUG_RETURN(ret);
diff --git a/sql/wsrep_high_priority_service.cc b/sql/wsrep_high_priority_service.cc
index 452242dfd23..8fd7d08d543 100644
--- a/sql/wsrep_high_priority_service.cc
+++ b/sql/wsrep_high_priority_service.cc
@@ -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);
int ret= (trans_rollback_stmt(m_thd) || trans_rollback(m_thd));
m_thd->release_transactional_locks();
+ mysql_ull_cleanup(m_thd);
m_thd->mdl_context.release_explicit_locks();
free_root(m_thd->mem_root, MYF(MY_KEEP_PREALLOC));