MySQL中INSERT/UPDATE/DELETE默认不走事务,是因为autocommit=1开启,每条DML执行后立即隐式提交、不可回滚;需SET autocommit=0或START TRANSACTION显式开启事务,并配合COMMIT/ROLLBACK手动控制,且仅InnoDB等支持事务的引擎生效。

MySQL事务不能自动保证DML操作一致性,必须显式控制提交/回滚时机,且仅对支持事务的存储引擎(如InnoDB)生效。
为什么INSERT/UPDATE/DELETE默认不走事务
MySQL默认开启autocommit=1,每条DML语句执行完立即隐式提交,无法回滚。这意味着哪怕你写了两条UPDATE,中间出错也无法撤回第一条。
- 查当前模式:
SELECT @@autocommit;—— 返回1即自动提交 - 临时关闭(当前会话):
SET SESSION autocommit = 0; - 注意:
SET GLOBAL autocommit = 0会影响所有新连接,生产环境慎用 - MyISAM等引擎不支持事务,即使关了
autocommit也无效
手动事务的最小安全写法
不是加个BEGIN就万事大吉,漏掉COMMIT或ROLLBACK会导致连接一直持有锁、事务长时间未结束。
- 标准三步:
START TRANSACTION;→ 执行DML →COMMIT;或ROLLBACK; - 推荐用
START TRANSACTION而非BEGIN,语义更明确,兼容性更好 - 如果DML中某条报错(比如违反唯一约束),MySQL不会自动回滚整个事务,需应用层捕获错误后主动调
ROLLBACK - 示例:
START TRANSACTION; UPDATE accounts SET balance = balance - 100 WHERE id = 1; UPDATE accounts SET balance = balance + 100 WHERE id = 2; -- 若第二条失败,必须手动 ROLLBACK,否则第一条已生效 COMMIT;
SAVEPOINT不是万能补丁,慎用于复杂流程
保存点只在当前事务内有效,且COMMIT后自动清除;滥用会导致逻辑混乱、回滚范围误判。
- 设保存点:
SAVEPOINT sp1; - 回退到该点:
ROLLBACK TO sp1;(注意不是ROLLBACK TO SAVEPOINT sp1) - 后续再设
SAVEPOINT sp2,然后ROLLBACK TO sp1,sp2会被自动删除 - 不要指望靠保存点替代业务层的状态校验——它解决不了跨表约束冲突、应用逻辑错误等问题
隔离级别直接影响“一致性”的实际表现
即使事务正确提交,不同隔离级别下,其他会话看到的数据状态可能完全不同。所谓“一致”,是相对于你设定的隔离级别而言的。
- 查看当前级别:
SELECT @@transaction_isolation; - InnoDB默认是
REPEATABLE-READ,能防止脏读和不可重复读,但幻读仍可能发生 - 若业务要求强一致性(如金融对账),需结合
SELECT ... FOR UPDATE加行锁,而不是只依赖隔离级别 - 升级到
SERIALIZABLE会极大降低并发性能,通常不推荐,优先考虑应用层重试或乐观锁
真正容易被忽略的是:事务一致性不等于业务一致性。比如转账时余额没超限、但扣款前账户已被冻结,这类校验必须在事务内用SELECT ... FOR UPDATE加锁后显式判断,光靠ACID机制覆盖不到。


















