调用startTransaction后未提交回滚的TypeORM废弃事务会如何处理
TypeORM事务未手动提交/回滚问题解答
1. TypeORM是否会自动回滚未处理的事务?
不会。你代码中在try块内触发业务校验直接return的场景,既不会走提交逻辑,也不会进入catch块的回滚逻辑,TypeORM没有内置自动回滚这类事务的机制,所以你在TypeORM的运行日志中看不到对应的rollback记录。
2. 释放queryRunner后未提交的变更会如何处理?
该场景的最终行为由底层数据库的ACID规则决定:所有主流关系型数据库(MySQL、PostgreSQL、SQL Server等)默认都会在未提交事务关联的数据库连接被关闭/释放回连接池时,自动回滚该事务,所有未提交的插入、更新操作都会被丢弃,不会持久化到数据库中。
注意这个回滚是数据库底层执行的,不是TypeORM触发的,所以不会在TypeORM的日志中留下记录。
3. 现有代码的隐患和优化方案
你的现有写法虽然最终不会产生脏数据,但存在两处明显问题:
- 事务回滚完全依赖数据库默认行为,若遇到特殊数据库配置(比如开启隐式提交、连接池释放时保留事务上下文等极端场景),可能出现数据异常
- 未及时结束事务会导致事务占用的行锁、表锁不能提前释放,提升锁冲突、死锁的概率,影响数据库并发性能
优化建议
- 在所有业务校验失败需要提前return的位置,先手动执行回滚再返回,示例如下:
const queryRunner = await getConnection().createQueryRunner(); try { await queryRunner.connect(); await queryRunner.startTransaction(); const t1 = await queryRunner.manager.getRepository(T1).findOneOrFail(opts); if(!t1) { await queryRunner.rollbackTransaction(); // 提前手动回滚 return Response.build(1001, 'not found'); } // 执行更新、插入逻辑 const t2 = await queryRunner.manager.getRepository(T2).findOneOrFail(opts); if(!t2) { await queryRunner.rollbackTransaction(); // 提前手动回滚 return Response.build(1001, 'not found'); } // 执行其他更新、插入逻辑 await queryRunner.commitTransaction(); } catch (e) { await queryRunner.rollbackTransaction(); } finally { await queryRunner.release(); }
- 你代码中
findOneOrFail查询后做空判断的逻辑是冗余的:findOneOrFail在匹配不到对应数据时会直接抛出EntityNotFoundError异常,自动进入catch块执行回滚,不需要额外做非空判断。
内容的提问来源于stack exchange,提问作者Mohd Waseem
相关产品推荐
相关产品推荐

