只有innodb支持真正的acid事务,myisam等引擎虽可执行begin但不支持回滚与行级锁;需通过show create table确认引擎,建表应显式指定engine=innodb。

只有 InnoDB 支持真正的事务
MySQL 的 MyISAM、Memory、CSV 等存储引擎根本不支持事务,执行 BEGIN 或 START TRANSACTION 后看似能“开启事务”,但实际无法回滚(ROLLBACK 无效),也不会真正加行级锁。只有 InnoDB(以及极小众的 NDB)具备 ACID 事务能力。
检查表引擎:用 SHOW CREATE TABLE table_name 看 ENGINE=InnoDB 是否存在;若为 MyISAM,即使写了 COMMIT,崩溃后也无持久化保障。
- 建表时不显式指定
ENGINE=InnoDB,可能受 MySQL 默认引擎影响(5.5+ 默认是 InnoDB,但老版本或定制实例可能不是) -
ALTER TABLE t ENGINE=InnoDB可在线转换,但大表会锁表较久,需评估窗口期 -
INSERT ... SELECT或批量导入时,若目标表是 MyISAM,整个过程不在事务内——哪怕外层套了START TRANSACTION
事务隔离级别直接影响并发行为
READ UNCOMMITTED 和 READ COMMITTED 下,InnoDB 使用“非锁定读”(快照读),不加 SELECT ... FOR UPDATE 就不会阻塞其他事务;而 REPEATABLE READ(MySQL 默认)会复用第一次读取的 MVCC 快照,导致“幻读”仍可能通过当前读触发(如 SELECT ... FOR UPDATE 扫描范围变化)。
常见误判:SELECT 不加锁 ≠ 没有并发风险——在 REPEATABLE READ 下,两次相同 SELECT 返回结果一致,但若中间有 INSERT 并提交,后续 SELECT ... FOR UPDATE 可能命中新行,引发逻辑错乱。
- 高并发计数场景慎用
REPEATABLE READ:比如“查余额 → 判断是否足够 → 扣款”,两次查可能看到同一快照,导致超扣 -
READ COMMITTED更贴近直觉,但 MVCC 版本清理更频繁,可能增加 purge 线程压力 - 修改隔离级别仅对当前连接有效:
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
显式加锁语句必须搭配事务使用
SELECT ... FOR UPDATE 和 SELECT ... LOCK IN SHARE MODE 不是独立操作,它们依赖事务上下文才能生效。如果在自动提交模式(autocommit=1)下执行,语句结束即释放锁,起不到保护临界区的作用。
系统功能强大、操作便捷并具有高度延续开发的内容与知识管理系统,并可集合系统强大的新闻、产品、下载、人才、留言、搜索引擎优化、等功能模块,为企业部门提供一个简单、易用、开放、可扩展的企业信息门户平台或电子商务运行平台。开发人员为脆弱页面专门设计了防刷新系统,自动阻止恶意访问和攻击;安全检查应用于每一处代码中,每个提交到系统查询语句中的变量都经过过滤,可自动屏蔽恶意攻击代码,从而全面防止SQL注入攻击
典型错误写法:SET autocommit = 1; SELECT * FROM account WHERE id = 1 FOR UPDATE; —— 锁在语句返回后立刻释放,后续 UPDATE 时已无锁保护。
- 务必先
START TRANSACTION(或SET autocommit = 0),再执行带锁SELECT,最后UPDATE+COMMIT -
FOR UPDATE在唯一索引上是行锁,在非唯一索引或无索引字段上可能升级为间隙锁(Gap Lock)甚至临键锁(Next-Key Lock),导致意外锁住范围 - 死锁检测由 InnoDB 自动完成,但日志里只报出
Deadlock found when trying to get lock,需结合SHOW ENGINE INNODB STATUS查具体锁等待链
长事务是并发性能隐形杀手
一个未提交的事务会持续持有锁、阻止 purge 线程清理旧版本,导致 information_schema.INNODB_TRX 中 TRX_ROWS_LOCKED 和 TRX_UNDO_BYTES 持续增长,最终拖慢整个实例的 DML 性能,甚至触发 innodb_lock_wait_timeout 超时。
开发中容易忽略的是“隐式长事务”:比如 ORM 框架开启事务后,因异常未走到 commit 分支,或 HTTP 请求处理完忘了关闭连接(连接池复用下事务状态残留)。
- 监控活跃事务时长:
SELECT * FROM information_schema.INNODB_TRX WHERE TRX_STARTED - 应用层应设置合理的事务超时(如 Spring 的
@Transactional(timeout = 30)),而非依赖数据库默认的 50 秒 - 避免在事务内做 RPC 调用、文件读写、用户交互等不可控耗时操作
事务和存储引擎的耦合比表面看起来更紧——引擎决定“能不能事务”,隔离级别决定“事务怎么并发”,而开发者对锁和生命周期的控制,才是真正决定系统是否扛得住并发的关键。很多线上问题不是语法写错,而是默认行为没被意识到。









