MySQL InnoDB事务中的SQL语句是否按顺序执行?会被重排吗?
InnoDB事务中多条独立DML语句的执行顺序说明
核心结论
针对你示例里拆分书写的多条独立UPDATE语句,InnoDB不会在逻辑层面重排执行顺序,会严格按照书写的先后次序依次执行。
关键细节说明
- 不同语句之间的执行边界是刚性的:每一条独立DML都是单独的执行单元,必须等前一条语句完成所有逻辑层操作(匹配行、加行锁、修改内存页数据、写入对应undo log)之后,才会启动下一条语句的执行。就拿你写的按id=1到id=n顺序排列的update语句来说,InnoDB一定会先处理id=1的行,拿到id=1对应的行锁,再处理id=2的行,不存在跨语句调换执行顺序的可能。
这个逻辑可以通过死锁场景直接验证:会话A开事务,先执行
update t_x ... where id=1(执行成功但不提交),再执行update t_x ... where id=2;会话B开事务,先持有id=2的行锁,再执行update t_x ... where id=1,两个会话必然触发死锁。如果InnoDB重排了语句顺序,这个死锁根本不会出现。 - 别把「单语句内部优化」当成跨语句重排:很多人误以为存在的顺序调整,其实都发生在单条DML内部——比如你写一条
update t_x ... where id in (1,2,3),优化器可能根据索引选择、统计信息调整行扫描顺序,但这是单条语句内部的执行策略,和你拆分写N条独立update的场景完全无关。 - 底层IO合并不影响上层逻辑顺序:InnoDB后台线程刷脏页、写redo log做物理持久化的时候,确实可能做IO合并、批量写入优化,但这是存储层的透明实现,完全不会改变上层逻辑的语句执行顺序、锁冲突规则、事务可见性结果,用户侧根本感知不到这类底层操作的调整。
快速验证方式
开一个事务,每执行一条update,就查询performance_schema.data_locks表看当前事务持有的行锁,你会发现行锁是按你执行语句的顺序逐个增加的,绝不会出现后面语句对应的行锁先被持有的情况。
内容的提问来源于stack exchange,提问作者kongwu
相关产品推荐
相关产品推荐

