答案是隔离级别修改未生效的主因在于会话级设置仅作用于当前连接、全局设置仅影响新连接、事务未真正启动或配置未重启生效。需验证select @@transaction_isolation、强制重连、检查配置格式及重启mysql服务,并确认事务是否通过首次select/dml触发快照生成。

修改的是会话级,但连接没重连
你执行了 SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ,但后续查询仍像在 READ COMMITTED 下行为——大概率是客户端(如 Navicat、DBeaver、MySQL Shell)复用了已有连接。MySQL 的会话级设置只对当前连接生效,而很多 GUI 工具建立连接后长期复用,不会因你改了隔离级别就自动断开重连。
- 验证方式:执行
SELECT @@transaction_isolation,看返回值是否为你设的级别 - 若返回值不对,说明连接未应用新设置;强制重连(关掉再开 SQL 标签页 / 重启终端)是最直接的解决办法
- 某些驱动(如 PyMySQL、mysql-connector-python)默认开启连接池,
SET SESSION只影响当次获取的连接,下次get_connection()可能拿到旧配置的连接
全局设置只对新连接生效
SET GLOBAL transaction_isolation = 'REPEATABLE-READ' 不会让已存在的连接立刻切换隔离级别。它只改变 MySQL 启动后新建连接的默认值。老连接继续用自己初始化时继承的级别,哪怕全局配置早已变更。
- 检查当前全局默认值:
SELECT @@global.transaction_isolation - 想让所有连接统一,必须配合服务重启(或逐个重连),不能只靠
SET GLOBAL - 配置文件(
my.cnf)里写transaction-isolation = 'REPEATABLE-READ'也一样:只有 mysqld 重启后才对新连接起效
事务根本没真正启动
很多人以为 BEGIN 一执行,事务和它的隔离级别就“活”了。其实不是:第一次 SELECT 或 DML 才真正触发事务启动并生成 Read View。如果只执行 BEGIN 然后就查 @@transaction_isolation,看到的是会话设置值,但 MVCC 快照还没建,后续读取可能仍受上一个事务或 autocommit 行为干扰。
- 构造可复现场景:执行
BEGIN; SELECT * FROM t WHERE id=1;(触发快照),再另起连接改数据并COMMIT,回到原连接再SELECT—— 这时才能验证是否真走快照读 - 如果第二次
SELECT结果变了,说明第一次读没锁定快照,极可能是事务延迟启动或引擎非 InnoDB - 用
SHOW ENGINE INNODB STATUS\G查TRANSACTIONS段,确认Trx started时间点是否早于你的第一次 SELECT
配置文件写错或没重启
在 my.cnf 里配隔离级别,两个细节最容易被忽略:一是用下划线 transaction_isolation,二是改完没重启 mysqld。MySQL 只认 transaction-isolation(短横线),且只在启动时加载一次。
- 错误写法:
transaction_isolation = READ-COMMITTED→ 静默忽略,配置无效 - 正确写法:
transaction-isolation = 'READ-COMMITTED'(推荐加引号,大小写不敏感但全大写更稳) - 改完配置必须执行
sudo systemctl restart mysql(或对应平台命令),kill -9强杀进程会导致配置不重载
真正生效的关键不在命令有没有输对,而在于「谁在用这个设置」——是当前连接?还是下一个新连接?又或者压根还没走到事务启动那一步。隔离级别不是开关,它得依附在活跃事务的生命周期里才起作用。











