Sequelize 事务(Transactions)全面指南

Sequelize 事务(Transactions)全面指南

【免费下载链接】sequelize-docs-Zh-CN 【免费下载链接】sequelize-docs-Zh-CN 项目地址: https://gitcode.com/gh_mirrors/se/sequelize-docs-Zh-CN

什么是数据库事务

数据库事务是指作为单个逻辑工作单元执行的一系列操作,要么完全执行,要么完全不执行。事务具有四个关键特性(ACID):

  • 原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不完成
  • 一致性(Consistency):事务执行前后,数据库从一个一致状态变到另一个一致状态
  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务
  • 持久性(Durability):事务一旦提交,其结果就是永久性的

Sequelize 中的事务类型

Sequelize 提供了两种使用事务的方式,各有适用场景:

1. 非托管事务(手动管理)

非托管事务需要开发者手动控制事务的提交(commit)和回滚(rollback)。这种方式提供了最大的灵活性,但也需要更多的代码管理。

// 开始事务
const t = await sequelize.transaction();

try {
  // 执行数据库操作,传递事务对象
  const user = await User.create({...}, { transaction: t });
  
  // 更多操作...
  
  // 手动提交事务
  await t.commit();
} catch (error) {
  // 出错时手动回滚
  await t.rollback();
}

适用场景

  • 需要精细控制事务流程
  • 事务中需要处理非数据库操作
  • 复杂的事务逻辑

2. 托管事务(自动管理)

托管事务由 Sequelize 自动管理提交和回滚,开发者只需关注业务逻辑。

try {
  const result = await sequelize.transaction(async (t) => {
    // 在此回调中执行操作
    const user = await User.create({...}, { transaction: t });
    return user;
  });
  // 事务已自动提交
} catch (error) {
  // 事务已自动回滚
}

优势

  • 代码更简洁
  • 减少忘记提交/回滚的风险
  • 错误处理更简单

高级事务特性

事务隔离级别

Sequelize 支持标准的事务隔离级别:

const { Transaction } = require('@sequelize/core');

// 可用的隔离级别
Transaction.ISOLATION_LEVELS.READ_UNCOMMITTED  // 读未提交
Transaction.ISOLATION_LEVELS.READ_COMMITTED    // 读已提交
Transaction.ISOLATION_LEVELS.REPEATABLE_READ   // 可重复读
Transaction.ISOLATION_LEVELS.SERIALIZABLE      // 串行化

设置隔离级别:

await sequelize.transaction({
  isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE
}, async (t) => {
  // 事务代码
});

并发事务处理

Sequelize 支持嵌套事务和并发事务(除SQLite外):

sequelize.transaction((t1) => {
  return sequelize.transaction((t2) => {
    // 可以明确指定每个操作使用哪个事务
    return Promise.all([
      User.create({...}, { transaction: null }),  // 不使用事务
      User.create({...}, { transaction: t1 }),    // 使用外层事务
      User.create({...})                          // 默认使用当前事务(t2)
    ]);
  });
});

事务钩子(afterCommit)

可以在事务提交后执行特定操作:

await sequelize.transaction(async (t) => {
  t.afterCommit(() => {
    // 事务提交后执行的代码
    // 适合发送通知、触发后续流程等
  });
  
  // 事务操作...
});

注意:如果事务回滚,afterCommit钩子不会执行。

最佳实践

  1. 生产环境必须使用事务:确保数据一致性
  2. 合理选择事务类型
    • 简单操作使用托管事务
    • 复杂逻辑使用非托管事务
  3. 注意事务范围:不要在不必要的情况下使用长事务
  4. 处理死锁:准备好重试逻辑
  5. 结合模型钩子使用:如afterSave等

常见问题解决方案

问题1:如何在整个应用中自动传递事务?

解决方案:使用CLS(Continuation Local Storage):

const cls = require('cls-hooked');
const namespace = cls.createNamespace('my-app-namespace');
const { Sequelize } = require('@sequelize/core');

// 全局启用CLS
Sequelize.useCLS(namespace);

// 之后创建的所有实例都会自动支持CLS
const sequelize = new Sequelize(...);

启用后,事务会自动在回调链中传递,无需手动指定。

问题2:如何在事务中使用锁?

解决方案

// 使用行锁
await User.findAll({
  where: { id: 123 },
  lock: true,
  transaction: t
});

// 跳过已锁定的行
await User.findAll({
  where: { status: 'active' },
  lock: true,
  skipLocked: true,
  transaction: t
});

通过本指南,你应该已经掌握了Sequelize中事务的核心概念和使用方法。合理使用事务可以显著提高应用的可靠性和数据一致性。

【免费下载链接】sequelize-docs-Zh-CN 【免费下载链接】sequelize-docs-Zh-CN 项目地址: https://gitcode.com/gh_mirrors/se/sequelize-docs-Zh-CN

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值