node prisma+postgreSQL数据库事务

在postgreSQL中,使用begin命令或start transition命令可以开启一个事务,使用commit命令或rollback命令可以回滚一个事务。

数据库的事务通常由一组DML语句(以insert、update和delete命令为核心的语句)组成,通过事务可以保证数据库中数据的完整性,保证这一组DML语句要么全部执行,要么全部不执行。

可以把事务看成:一个逻辑工作单元,可以通过提交或回滚操作来结束一个事务

数据库的四个特性如下:

|----------------|--------------------------------------|
| 特性 | 说明 |
| Atomicity原子性 | 事务中的操作要不全做,要不全不做,事务 执行失败时,会回滚到执行前的状态 |
| Consistency一致性 | 事务执行前后,数据库从一个一致状态到另一个 一致状态 |
| Isolation隔离性 | 并发事务互不干扰 |
| Durability持久性 | 事务一旦提交,其结果永久保存 |

prisma的两个事务

|-------|---------------------------------|-----------------|
| 方式 | 语法 | 适用场景 |
| 交互式事务 | transaction(async(tx)=\>{...}) | 需要在事务中做判断,有条件逻辑 | | 批量事务 | transaction(op1, op2, ...) | 多个独立操作原子执行 |

使用prisma进行数据库事务时,要遵循下面三个原则:

1 只包含数据库操作

2 预先计算好数据,减少事务内判断

3 大批量操作分批执行

常用事务使用示例

交互式事务, 场景:创建用户 + 同时创建2篇文章,全部成功或全部回滚

javascript 复制代码
// 场景:创建用户 + 同时创建2篇文章,全部成功或全部回滚
const result = await prisma.$transaction(async (tx) => {
  // tx 是事务专用的 PrismaClient,所有操作在同一个事务中
  const user = await tx.user.create({
    data: {
      email: 'tx-demo@test.com',
      name: '事务演示用户',
      password: '123456',
    },
  })
  const post1 = await tx.post.create({
    data: {
      title: '事务中的文章1',
      published: true,
      authorId: user.id,
    },
  })
  const post2 = await tx.post.create({
    data: {
      title: '事务中的文章2',
      published: false,
      authorId: user.id,
    },
  })
})
  return { user, post1, post2 }

批量事务

javascript 复制代码
// 多个独立操作原子执行
const [updatedUser, createdPost, userCount] = await prisma.$transaction([
  // 操作1:更新用户名
  prisma.user.update({
    where: { id: 1 },
    data: { name: '新名字' },
  }),
  // 操作2:创建文章
  prisma.post.create({
    data: { title: '新文章', authorId: 1 },
  }),
  // 操作3:统计
  prisma.user.count(),
])
// 三个操作要么全成功,要么全失败

手动回滚:p2000是一种数据库错误类型(字段值过长),clientVersion是类似自己代码的版本

javascript 复制代码
import { Prisma } from '@prisma/client'
await prisma.$transaction(async (tx) => {
  // ... 一些操作
  // 手动触发回滚
  throw new Prisma.PrismaClientKnownRequestError(
    '业务原因回滚',
    { code: 'P2000', clientVersion: '5.0.0' }
  )
})

设置隔离级别与超时

javascript 复制代码
import { PrismaClient, Prisma } from '@prisma/client'
const prisma = new PrismaClient()

async function runTransaction() {
  try {
    const result = await prisma.$transaction(
      async (tx) => {
        // 在此处执行事务操作,使用 tx 代替 prisma
        const user = await tx.user.create({ data: { name: 'Alice' } })
        const account = await tx.account.create({ data: { userId: user.id, balance: 100 } })
        return { user, account }
      },
      {
        //这里统一设置一些事务的配置属性
        isolationLevel: Prisma.TransactionIsolationLevel.Serializable, // 设置隔离级别
        timeout: 10000, // 事务整体超时时间(毫秒),默认 5000ms
        maxWait: 5000,  // 等待获取事务执行权的最大时间(毫秒),默认 2000ms
      }
    )
    console.log('Transaction succeeded:', result)
  } catch (error) {
    console.error('Transaction failed:', error)
  }
}
相关推荐
guslegend8 小时前
脚手架入门:必要性、核心功能与执行原理
前端·架构·node.js·脚手架·前端工程化
HaipengYu1 天前
深度解密 OpenCode 2 插件加载机制:Dual-Version (V1/V2) 适配实战与官方文档的“隐形陷阱”
node.js
前端之虎陈随易1 天前
bm2,Node.js 与 Bun 项目部署新选择
node.js
梦帮科技3 天前
【3.0修订版】 RNS 代币架构:ERC20 五件套扩展与六钱包分配
数据结构·后端·算法·架构·node.js·区块链·php
niyongsheng3 天前
后端零改动,给若依换一套现代化前端
vue.js·开源·node.js
liangshanbo12153 天前
面试题:Webpack 的 publicPath 有什么作用?
前端·webpack·node.js
hasty4 天前
不上传新包,也能改变用户拿到的版本:npm dist-tag 的 OIDC 权限治理
前端·npm·node.js
福兮说5 天前
前后端算的 MD5、SHA-256 对不上?编码、换行、BOM、HMAC、JSON 顺序,八个原因逐个实测
前端·javascript·node.js·json·哈希算法
lingchen19065 天前
Node.js的下载安装配置
node.js
LRL_5 天前
【实战指南】Node.js 跨平台依赖下载:如何在 Windows/Linux 环境下互跨下载目标系统的 npm/pnpm 包
linux·windows·node.js