平凯数据库事务内修改隔离级别
开启全局系统变量 pkdb_eal 后,你可以在已经开始的悲观事务中执行 SET TRANSACTION ISOLATION LEVEL ...,在不结束当前事务的前提下,在 REPEATABLE READ 与 READ COMMITTED 之间切换当前事务的隔离级别。
这个能力适用于需要在同一个事务里临时调整读取可见性的场景。例如:
- 从
REPEATABLE READ切换到READ COMMITTED后,后续读取可以看到其他事务新提交的数据。 - 从
READ COMMITTED切换回REPEATABLE READ后,后续读取会回到当前事务开始时的快照。 - 事务即使已经读取过数据,后续仍然可以继续切换。
使用前提与开启方式
使用该能力前,需要满足以下条件:
- 当前事务已经开始。
- 当前事务是悲观事务。建议直接使用
BEGIN PESSIMISTIC。 - 全局系统变量
pkdb_eal已开启。
开启方式如下:
SHOW GLOBAL VARIABLES LIKE 'pkdb_eal';
SET GLOBAL pkdb_eal = ON;
事务内支持的切换语法如下:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SQL 示例
示例 1:在当前事务中从 REPEATABLE READ 切换到 READ COMMITTED
先准备测试表:
DROP TABLE IF EXISTS demo_change_isolation_accounts;
CREATE TABLE demo_change_isolation_accounts (
id INT PRIMARY KEY,
balance INT
);
INSERT INTO demo_change_isolation_accounts VALUES (1, 1000);
会话 1:
SET GLOBAL pkdb_eal = ON;
SET SESSION transaction_isolation = 'REPEATABLE-READ';
BEGIN PESSIMISTIC;
SELECT balance FROM demo_change_isolation_accounts WHERE id = 1;
-- 1000
会话 2:
BEGIN PESSIMISTIC;
UPDATE demo_change_isolation_accounts SET balance = 1200 WHERE id = 1;
COMMIT;
会话 1:
SELECT balance FROM demo_change_isolation_accounts WHERE id = 1;
-- 1000
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT balance FROM demo_change_isolation_accounts WHERE id = 1;
-- 1200
COMMIT;
DROP TABLE demo_change_isolation_accounts;
示例 2:在当前事务中从 READ COMMITTED 切换到 REPEATABLE READ
先准备测试表:
DROP TABLE IF EXISTS demo_change_isolation_accounts;
CREATE TABLE demo_change_isolation_accounts (
id INT PRIMARY KEY,
balance INT
);
INSERT INTO demo_change_isolation_accounts VALUES (1, 1000);
会话 1:
SET GLOBAL pkdb_eal = ON;
SET SESSION transaction_isolation = 'READ-COMMITTED';
BEGIN PESSIMISTIC;
SELECT balance FROM demo_change_isolation_accounts WHERE id = 1;
-- 1000
会话 2:
BEGIN PESSIMISTIC;
UPDATE demo_change_isolation_accounts SET balance = 800 WHERE id = 1;
COMMIT;
会话 1:
SELECT balance FROM demo_change_isolation_accounts WHERE id = 1;
-- 800
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT balance FROM demo_change_isolation_accounts WHERE id = 1;
-- 1000
COMMIT;
DROP TABLE demo_change_isolation_accounts;
注意事项与限制
- 已开始的悲观事务,且
pkdb_eal = ON: 支持在当前事务内把隔离级别从REPEATABLE READ切到READ COMMITTED,也支持反向切换。 - 事务已经读过数据后再切换: 仍然生效,后续读取按切换后的隔离级别表现。
- 已开始的悲观事务,但
pkdb_eal = OFF: 语句会报错:ERROR 1568 (25001)。 - 乐观事务: 语句不会改变当前事务的读取行为。
START TRANSACTION READ ONLY AS OF TIMESTAMP ...: 语句不会改变当前 stale read 事务的快照。- 事务外执行: 这不是本文功能的使用方式;它不会改写
transaction_isolation。如果你的目标是修改后续事务的默认隔离级别,请使用SET SESSION transaction_isolation = ...。 SELECT ... FOR UPDATE: 切换后仍然保持悲观锁语义。SAVEPOINT: 切换后仍然可以继续使用ROLLBACK TO SAVEPOINT。