From a06e81cbdf9b517d784801fb4db7f34ee9314628 Mon Sep 17 00:00:00 2001 From: Ahmad Date: Tue, 17 Feb 2026 00:51:54 +0200 Subject: [PATCH 1/2] MDEV-27837: Disallow SET @@session.server_id within transaction Setting server_id within a transaction is dangerous for replication. Added check_not_in_transaction validation to server_id variable. --- .../r/set_server_id_inside_transaction.result | 39 ++++++++++++++ .../t/set_server_id_inside_transaction.test | 51 +++++++++++++++++++ sql/sys_vars.cc | 7 +++ 3 files changed, 97 insertions(+) create mode 100644 mysql-test/suite/sys_vars/r/set_server_id_inside_transaction.result create mode 100644 mysql-test/suite/sys_vars/t/set_server_id_inside_transaction.test diff --git a/mysql-test/suite/sys_vars/r/set_server_id_inside_transaction.result b/mysql-test/suite/sys_vars/r/set_server_id_inside_transaction.result new file mode 100644 index 0000000000000..f8ffea335c556 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/set_server_id_inside_transaction.result @@ -0,0 +1,39 @@ +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +# +# Test that SET @@session.server_id fails inside explicit transaction +# +BEGIN; +INSERT INTO t1 VALUES (1); +SET @@session.server_id = 100; +ERROR 25000: You are not allowed to execute this command in a transaction +ROLLBACK; +# +# Test that SET @@session.server_id works outside transaction +# +SET @@session.server_id = 100; +SELECT @@session.server_id; +@@session.server_id +100 +# +# Test that SET @@session.server_id fails with autocommit=0 +# +SET autocommit = 0; +INSERT INTO t1 VALUES (2); +SET @@session.server_id = 200; +ERROR 25000: You are not allowed to execute this command in a transaction +ROLLBACK; +SET autocommit = 1; +# +# Test that SET @@session.server_id works after COMMIT +# +BEGIN; +INSERT INTO t1 VALUES (3); +COMMIT; +SET @@session.server_id = 300; +SELECT @@session.server_id; +@@session.server_id +300 +# +# Cleanup +# +DROP TABLE t1; diff --git a/mysql-test/suite/sys_vars/t/set_server_id_inside_transaction.test b/mysql-test/suite/sys_vars/t/set_server_id_inside_transaction.test new file mode 100644 index 0000000000000..7c9d92e6d6157 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/set_server_id_inside_transaction.test @@ -0,0 +1,51 @@ +--source include/have_innodb.inc + +# +# MDEV-27837: Disallow SET @@session.server_id within transaction +# + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; + +--echo # +--echo # Test that SET @@session.server_id fails inside explicit transaction +--echo # + +BEGIN; +INSERT INTO t1 VALUES (1); +--error ER_CANT_DO_THIS_DURING_AN_TRANSACTION +SET @@session.server_id = 100; +ROLLBACK; + +--echo # +--echo # Test that SET @@session.server_id works outside transaction +--echo # + +SET @@session.server_id = 100; +SELECT @@session.server_id; + +--echo # +--echo # Test that SET @@session.server_id fails with autocommit=0 +--echo # + +SET autocommit = 0; +INSERT INTO t1 VALUES (2); +--error ER_CANT_DO_THIS_DURING_AN_TRANSACTION +SET @@session.server_id = 200; +ROLLBACK; + +SET autocommit = 1; + +--echo # +--echo # Test that SET @@session.server_id works after COMMIT +--echo # + +BEGIN; +INSERT INTO t1 VALUES (3); +COMMIT; +SET @@session.server_id = 300; +SELECT @@session.server_id; + +--echo # +--echo # Cleanup +--echo # +DROP TABLE t1; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 5fe3eb4586b20..78fdcf825d201 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3375,6 +3375,13 @@ static bool check_server_id(sys_var *self, THD *thd, set_var *var) return true; } #endif /* WITH_WSREP */ + + if (error_if_in_trans_or_substatement( + thd, + ER_CANT_DO_THIS_DURING_AN_TRANSACTION, + ER_CANT_DO_THIS_DURING_AN_TRANSACTION)) + return true; + return false; } From d1a9df0885c5be5082df8412782fcdee5345f7a0 Mon Sep 17 00:00:00 2001 From: Ahmad Date: Tue, 17 Feb 2026 17:31:42 +0200 Subject: [PATCH 2/2] MDEV-27837: Address review comments - Add specific error codes ER_CANT_SET_SERVER_ID_IN_TRANSACTION and ER_CANT_SET_SERVER_ID_IN_SUBSTATEMENT - Extend test to cover trigger and stored procedure cases --- .../r/set_server_id_inside_transaction.result | 41 ++++++++++++- .../t/set_server_id_inside_transaction.test | 57 ++++++++++++++++--- sql/share/errmsg-utf8.txt | 4 ++ sql/sys_vars.cc | 4 +- 4 files changed, 95 insertions(+), 11 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/set_server_id_inside_transaction.result b/mysql-test/suite/sys_vars/r/set_server_id_inside_transaction.result index f8ffea335c556..3e7710e3b8683 100644 --- a/mysql-test/suite/sys_vars/r/set_server_id_inside_transaction.result +++ b/mysql-test/suite/sys_vars/r/set_server_id_inside_transaction.result @@ -5,7 +5,7 @@ CREATE TABLE t1 (a INT) ENGINE=InnoDB; BEGIN; INSERT INTO t1 VALUES (1); SET @@session.server_id = 100; -ERROR 25000: You are not allowed to execute this command in a transaction +ERROR HY000: Cannot set @@session.server_id within a transaction ROLLBACK; # # Test that SET @@session.server_id works outside transaction @@ -20,7 +20,7 @@ SELECT @@session.server_id; SET autocommit = 0; INSERT INTO t1 VALUES (2); SET @@session.server_id = 200; -ERROR 25000: You are not allowed to execute this command in a transaction +ERROR HY000: Cannot set @@session.server_id within a transaction ROLLBACK; SET autocommit = 1; # @@ -34,6 +34,43 @@ SELECT @@session.server_id; @@session.server_id 300 # +# Test that SET @@session.server_id fails inside a trigger +# +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +CREATE TRIGGER tr1 BEFORE INSERT ON t2 FOR EACH ROW +SET @@session.server_id = 100; +INSERT INTO t2 VALUES (1); +ERROR HY000: Cannot set @@session.server_id within a trigger or stored program +DROP TRIGGER tr1; +DROP TABLE t2; +# +# Test that SET @@session.server_id fails inside a stored procedure +# called within a transaction +# +CREATE PROCEDURE sp1() +BEGIN +SET @@session.server_id = 100; +END// +BEGIN; +CALL sp1(); +ERROR HY000: Cannot set @@session.server_id within a transaction +ROLLBACK; +DROP PROCEDURE sp1; +# +# Test that SET @@session.server_id fails inside a stored procedure +# that starts its own transaction +# +CREATE PROCEDURE sp2() +BEGIN +START TRANSACTION; +INSERT INTO t1 VALUES (1); +SET @@session.server_id = 100; +COMMIT; +END// +CALL sp2(); +ERROR HY000: Cannot set @@session.server_id within a transaction +DROP PROCEDURE sp2; +# # Cleanup # DROP TABLE t1; diff --git a/mysql-test/suite/sys_vars/t/set_server_id_inside_transaction.test b/mysql-test/suite/sys_vars/t/set_server_id_inside_transaction.test index 7c9d92e6d6157..865542b400904 100644 --- a/mysql-test/suite/sys_vars/t/set_server_id_inside_transaction.test +++ b/mysql-test/suite/sys_vars/t/set_server_id_inside_transaction.test @@ -9,43 +9,86 @@ CREATE TABLE t1 (a INT) ENGINE=InnoDB; --echo # --echo # Test that SET @@session.server_id fails inside explicit transaction --echo # - BEGIN; INSERT INTO t1 VALUES (1); ---error ER_CANT_DO_THIS_DURING_AN_TRANSACTION +--error ER_CANT_SET_SERVER_ID_IN_TRANSACTION SET @@session.server_id = 100; ROLLBACK; --echo # --echo # Test that SET @@session.server_id works outside transaction --echo # - SET @@session.server_id = 100; SELECT @@session.server_id; --echo # --echo # Test that SET @@session.server_id fails with autocommit=0 --echo # - SET autocommit = 0; INSERT INTO t1 VALUES (2); ---error ER_CANT_DO_THIS_DURING_AN_TRANSACTION +--error ER_CANT_SET_SERVER_ID_IN_TRANSACTION SET @@session.server_id = 200; ROLLBACK; - SET autocommit = 1; --echo # --echo # Test that SET @@session.server_id works after COMMIT --echo # - BEGIN; INSERT INTO t1 VALUES (3); COMMIT; SET @@session.server_id = 300; SELECT @@session.server_id; +--echo # +--echo # Test that SET @@session.server_id fails inside a trigger +--echo # +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +CREATE TRIGGER tr1 BEFORE INSERT ON t2 FOR EACH ROW + SET @@session.server_id = 100; +--error ER_CANT_SET_SERVER_ID_IN_SUBSTATEMENT +INSERT INTO t2 VALUES (1); +DROP TRIGGER tr1; +DROP TABLE t2; + +--echo # +--echo # Test that SET @@session.server_id fails inside a stored procedure +--echo # called within a transaction +--echo # +--delimiter // + +CREATE PROCEDURE sp1() +BEGIN + SET @@session.server_id = 100; +END// + +--delimiter ; + +BEGIN; +--error ER_CANT_SET_SERVER_ID_IN_TRANSACTION +CALL sp1(); +ROLLBACK; +DROP PROCEDURE sp1; + +--echo # +--echo # Test that SET @@session.server_id fails inside a stored procedure +--echo # that starts its own transaction +--echo # +--delimiter // +CREATE PROCEDURE sp2() +BEGIN + START TRANSACTION; + INSERT INTO t1 VALUES (1); + SET @@session.server_id = 100; + COMMIT; +END// +--delimiter ; +--error ER_CANT_SET_SERVER_ID_IN_TRANSACTION +CALL sp2(); +DROP PROCEDURE sp2; + --echo # --echo # Cleanup --echo # DROP TABLE t1; + diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index f0273c6cb7a82..ac42282884b7c 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -10036,3 +10036,7 @@ ER_REMOVED_ORPHAN_TRIGGER ER_STORAGE_ENGINE_DISABLED eng "Storage engine %s is disabled" spa "El motor de almacenaje %s está desactivado" +ER_CANT_SET_SERVER_ID_IN_TRANSACTION + eng "Cannot set @@session.server_id within a transaction" +ER_CANT_SET_SERVER_ID_IN_SUBSTATEMENT + eng "Cannot set @@session.server_id within a trigger or stored program" diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 78fdcf825d201..2c7e8330b6d84 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3378,8 +3378,8 @@ static bool check_server_id(sys_var *self, THD *thd, set_var *var) if (error_if_in_trans_or_substatement( thd, - ER_CANT_DO_THIS_DURING_AN_TRANSACTION, - ER_CANT_DO_THIS_DURING_AN_TRANSACTION)) + ER_CANT_SET_SERVER_ID_IN_SUBSTATEMENT, + ER_CANT_SET_SERVER_ID_IN_TRANSACTION)) return true; return false;