Sequelize
是 Node.js 的一个 ORM
库,通过 Sequelize
我们能用熟悉的 js 链接,操作数据库。工作需要,笔者日常工作除了切图,也开始要写后端代码了。由于缺乏经验,之前开发的功能在并发情况下出现了异常。深入理解之后重新回来梳理问题,并记录学习的笔记。
基础知识
事务(Transaction):事务是数据库执行过程中的一个逻辑单位,由一系列有限的数据库操作序列构成。被事务包裹起来的这些操作会有共同的执行结果,要么全部成功,要么失败,全部回滚。all-or-nothing
以银行转账为例子。用户 A 给 用户 B 转账 100。
伪代码(忽略细节)
A 余额 = A余额 - 100
B 余额 = B余额 + 100
复制代码
A 账号 -100,和 B 账号 +100 是两条独立的语句,如果在中间发生异常,导致程序中断,就会出现 A 账号上的 100 凭空消失。谁也不想看到这样的结果, 为了保证转账操作的原子性 ,用事务包裹起来。如果这中间发生错误,则会全部回滚。
start transaction;
// 转账操作
commit;
复制代码
Terminal 中演示 transaction
的作用。
Sequelize
提供了 Transaction
类,通过 Sequelize.transaction
创建事务,并在每一次数据库操作设置当前操作属于哪个事务。
await sequelize.transaction({}, async (transaction) => {
const instance = await Accounts.findOne({
where: {
name: 'HelKyle',
},
transaction,
});
await instance.update({
balances: instance.balances + number,
}, {
transaction,
})
})
复制代码
从 Squelize log 中能看到,创建了事务 id 为444a5afe-9635-40fd-90d7-10f5aa16077a
,之后的查询,更新都在这个事务中运行。
Executing (444a5afe-9635-40fd-90d7-10f5aa16077a): START TRANSACTION;
Executing (444a5afe-9635-40fd-90d7-10f5aa16077a): SELECT "name", "balances" FROM "accounts" AS "accounts" WHERE