mysql事务隔离级别支持在线修改:会话级可随时修改且仅影响当前连接,全局级修改只对新连接生效;配置文件中需用transaction-isolation=read-committed(短横线、全大写推荐加引号),重启后才生效。

MySQL 事务隔离级别能在线修改吗
能,但分两种情况:会话级和全局级。会话级随时可改,不影响别人;全局级改了只影响新连接,当前已连上的连接不变。
常见错误是以为 SET GLOBAL transaction_isolation = 'READ-COMMITTED' 一执行,所有连接立刻生效——其实老连接还用着原来的隔离级别,得重连才感知到新配置。
- 查看当前会话级别:
SELECT @@transaction_isolation - 查看全局默认值:
SELECT @@global.transaction_isolation - 临时改当前会话:
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED - 永久改默认(需重启或配合配置文件):
SET GLOBAL transaction_isolation = 'READ-COMMITTED'
my.cnf 里怎么配 isolation level 才真正生效
直接写 transaction-isolation = READ-COMMITTED 在 [mysqld] 段就行,但注意格式:必须用短横线(-),不能写成下划线(_),否则 MySQL 启动时会静默忽略这行。
另外,这个配置只在 mysqld 启动时读取一次。如果改了 my.cnf 却没重启服务,或者用 mysqladmin shutdown 以外的方式停库(比如 kill -9),新配置永远不会加载。
- 正确写法:
transaction-isolation = READ-COMMITTED - 错误写法:
transaction_isolation = READ-COMMITTED(下划线,无效) - 值必须全大写、带引号?不,MySQL 接受大小写混合,但推荐全大写加单引号更稳妥:
transaction-isolation = 'READ-COMMITTED'
READ-COMMITTED 和 REPEATABLE-READ 的实际行为差异在哪
关键不是“能不能读到新数据”,而是“同一事务内多次 SELECT 是否看到相同结果”。REPEATABLE-READ 下,第一次 SELECT 后,后续 SELECT 会复用快照,哪怕其他事务已提交;READ-COMMITTED 每次 SELECT 都读最新已提交版本。
容易踩的坑是:在 REPEATABLE-READ 下执行 UPDATE 带子查询,子查询读的是事务启动时的快照,而 UPDATE 目标行可能已被其他事务改过,导致“幻读”或意外更新失败(尤其配合 SELECT ... FOR UPDATE 时)。
- REPEATABLE-READ 是 MySQL 默认,适合强一致性读场景,但 MVCC 开销略高
- READ-COMMITTED 更贴近 PostgreSQL/Oracle 行为,适合高并发写+容忍非重复读的业务
- 避免在 REPEATABLE-READ 下依赖“第二次 SELECT 肯定和第一次一样”来写逻辑,除非你明确控制了锁
ALTER TABLE 或 DDL 语句受隔离级别影响吗
完全不受影响。DDL(如 ALTER TABLE、DROP INDEX)在 MySQL 中是隐式提交操作,会强制结束当前事务,并且总是以最高隔离强度执行——它们不走 MVCC 快照,直接操作表结构元数据和存储引擎层。
这意味着:你在 REPEATABLE-READ 事务里执行 ALTER TABLE t ADD COLUMN x INT,执行完后该事务就结束了,后面再 SELECT 已不在原事务上下文中;同时,这条 DDL 本身不会被其他事务的隔离级别“挡住”或“绕开”,它会等所有相关表锁释放后立即执行。
- DDL 前如果有未提交的 DML,会被自动提交
- 不要指望用隔离级别来“保护 DDL 不被干扰”——锁机制才是关键
- 想确认 DDL 是否阻塞,看
SHOW PROCESSLIST里状态是不是Waiting for table metadata lock











