最近 koa2 项目中用到的 ORM 是 Sequelize V6,用户第一次登录时会在用户表、积分表、账本表等多个表中添加数据,还有其他场景,记录一下 Sequelize 中的事务如何使用,重点是托管事务
。
¶一、事务的定义
网上关于事务的定义有很多,简单理解为以下几点:
- 原子性:事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。
- 一致性:几个并行执行的事务,其执行结果必须与按某一顺序 串行执行的结果相一致。
- 隔离性:事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
- 持久性:对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。
¶二、Sequelize 中的事务
默认情况下,Sequelize 不使用事务,正常情况下生产环境是应该使用事务的。Sequelize 中支持两种使用方式,推荐托管事务
:
¶1、非托管事务
可参考:非托管事务
¶2、托管事务
托管事务会自动处理提交或回滚事务,通过将回调传递给sequelize.transaction
来启动托管事务,这个回调可以是async
的(通常是的)。在这种情况下,将发生以下情况:
- Sequelize 将自动开始事务并获得事务对象
t
- 将执行提供的回调,并在其中传递
t
- 如果回调抛出错误,Sequelize 将自动回滚事务
- 如果回调成功,Sequelize 将自动提交事务
sequelize.transaction
调用的两种结果:
- 1、回调执行完成
- 2、如果回调引发错误,则拒绝执行回调并抛出错误
1 | try { |
注意
t.commit()
和t.callback()
没有被直接调用。
¶3、抛出错误以回滚
使用托管事务时,不应手动执行t.commit()
和t.callback()
,如果回调成功,依旧想回滚事务,可手动抛出错误:
1 | await sequelize.transaction(async t => { |