这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战
并发或部分事务
可以在一系列查询中进行并发事务,也可以将某些事务排除在任何事务之外, 使用 transaction 参数来控制查询属于哪个事务:
注意一下SQLite, 不支持同时多个事务.*
启用 CLS
sequelize.transaction((t1) => {
return sequelize.transaction((t2) => {
// 启用 CLS 后,此处的查询默认情况下将使用 t2.
// 传递 `transaction` 参数以定义/更改它们所属的事务.
return Promise.all([
User.create({ name: 'Bob' }, { transaction: null }),
User.create({ name: 'Mallory' }, { transaction: t1 }),
User.create({ name: 'John' }) // 这将默认为 t2
]);
});
});
传递参数
sequelize.transaction 方法接受参数.
对于非托管事务,只需使用 sequelize.transaction(options).
对于托管交易,请使用 sequelize.transaction(options, callback).
隔离级别
启动事务时可能使用的隔离级别:
const { Transaction } = require('sequelize');
// 以下是有效的隔离级别:
Transaction.ISOLATION_LEVELS.READ_UNCOMMITTED // "READ UNCOMMITTED"
Transaction.ISOLATION_LEVELS.READ_COMMITTED // "READ COMMITTED"
Transaction.ISOLATION_LEVELS.REPEATABLE_READ // "REPEATABLE READ"
Transaction.ISOLATION_LEVELS.SERIALIZABLE // "SERIALIZABLE"
默认情况下, sequelize 使用数据库的隔离级别. 如果要使用其他隔离级别,传入所需的级别作为第一个参数:
const { Transaction } = require('sequelize');
await sequelize.transaction({
isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE
}, async (t) => {
// 你的代码
});
可以使用 Sequelize 构造函数中的一个参数来全局覆盖 isolationLevel 设置
const { Sequelize, Transaction } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory:', {
isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE
});
注意一下MSSQL, 因为指定的 isolationLevel 被直接传递给 tedious ,所以没有记录 SET ISOLATION LEVEL 查询
如果与其他 sequelize 方法一起使用
transaction 参数与大多数其他参数一起使用,通常是方法的第一个参数.
对于带有值的方法, 例如 .create,.update() 等.transaction 应该传递给第二个参数.
await User.create({ name: 'Foo Bar' }, { transaction: t });
await User.findAll({
where: {
name: 'Foo Bar'
},
transaction: t
});
afterCommit hook
一个 transaction 对象可以允许跟踪它是否以及何时被提交
可以将 afterCommit hook 添加到托管和非托管事务对象中
// 托管事务:
await sequelize.transaction(async (t) => {
t.afterCommit(() => {
// 你的代码
});
});
// 非托管事务:
const t = await sequelize.transaction();
t.afterCommit(() => {
// 你的代码
});
await t.commit();
传递给 afterCommit 的回调可以是 async:
- 对于托管交易:
sequelize.transaction调用将在完成之前等待它; - 对于非托管交易:
t.commit调用将在完成之前等待它.
注意:
- 如果事务回滚,则不会引发
afterCommithook; afterCommithook 不修改事务的返回值(与大多数 hook 不同)
可以将 afterCommit hook 与模型 hook 结合使用,以了解何时保存实例并在事务外部可用