应优先执行 SELECT @@autocommit 和 SELECT @@in_transaction 查看真实事务状态,而非依赖 SHOW VARIABLES;SET autocommit = 0 切换会话为手动提交模式,但 DDL 等仍会隐式提交,且连接池需配置 connection-init-sql 才生效。

直接执行 SET autocommit = 0 或 SET autocommit = 1 即可,但必须在连接建立后、任何业务语句前执行,否则可能被驱动覆盖或已隐式开启事务。
查当前会话真实 autocommit 状态,别信 SHOW VARIABLES
很多工具(如 Navicat)或驱动会在后台偷偷改值,SHOW VARIABLES LIKE 'autocommit' 返回的字符串(ON/OFF)不如直接查系统变量可靠:
-
SELECT @@autocommit—— 返回整数1(开)或0(关),结果明确,无歧义 -
SELECT @@in_transaction—— 更关键:返回1才说明你正处在活跃事务中;哪怕@@autocommit = 0,刚执行完ALTER TABLE后它也会变0,意味着前面操作已被隐式提交 - 生产排查“UPDATE 后查不到”“锁不释放”,第一步永远是这两个查询,不是翻配置文件
SET autocommit = 0 的副作用和边界行为
它不是“开启一个事务”,而是把整个会话切换成手动提交模式,后续所有 DML 都累积进同一个未结束事务,直到你显式 COMMIT 或 ROLLBACK:
-
DDL(如ALTER TABLE)、TRUNCATE TABLE、LOCK TABLES在autocommit = 0下仍会触发隐式COMMIT,导致前面的修改提前落库 - 如果忘记
COMMIT就关闭连接或归还连接池,事务会一直挂着,锁不释放,拖慢整个池 -
SET autocommit = 1会自动提交当前打开的事务(如果有),所以它既是开关,也是提交触发器
连接池里设 connection-init-sql 才算真正生效
JDBC、PyMySQL、PDO 等驱动建连后大概率会悄悄执行 setAutoCommit(false),哪怕 MySQL 服务端全局设了 SET GLOBAL autocommit = 1,新连上来还是 0:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- HikariCP:
spring.datasource.hikari.connection-init-sql=SET autocommit = 1 - Druid:
connectionInitSqls=["SET autocommit = 1"] - 别信
application.yml里的spring.datasource.hikari.auto-commit=true或default-auto-commit: true,这些配置项多数不生效 - 临时在代码里执行
SET autocommit = 1?晚了——事务可能已在第一条 SQL 执行时就隐式启了
START TRANSACTION 比 SET autocommit = 0 更安全
两者都能让下一条 DML 进入事务,但语义完全不同:
-
START TRANSACTION(或BEGIN)只临时关闭 autocommit,并初始化事务上下文;COMMIT或ROLLBACK后,autocommit 自动恢复原值(通常是1) -
SET autocommit = 0是会话级开关,影响后续所有语句,极易漏关,且无法感知事务是否意外延续 - 业务逻辑用
START TRANSACTION显式包裹,至少能清晰界定事务起点与终点,避免长事务锁表
最常被忽略的一点:autocommit 是每个连接独立的状态,不是数据库全局属性。你在连接 A 里设了 SET autocommit = 0,对连接 B 完全没影响;而连接池里没配 connection-init-sql,等于每条连接都在裸奔。










