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)
  }
}
相关推荐
badhope3 小时前
C++、Node.js、Python 写最小 HTTP 服务谁快?我实测了 6 万次请求
node.js
console.log('npc')4 小时前
03 — 核心框架:App 与中间件
后端·node.js·express
云浪4 小时前
从 0 手写一个 MCP Server:让 Copilot 调用 Tool 完成四则运算
javascript·node.js·mcp
FungLeo17 小时前
成为全栈·Node 后端篇·点赞系统:幂等点赞与计数原子增减
node.js·成为全栈·点赞系统·幂等点赞·计数原子增减
故作春风20 小时前
elpis-core 核心从入门到理解
后端·架构·node.js
万敏20 小时前
Vue3 全栈实战第九周:Node.js + Express 后端从零搭建实战记录
vue.js·node.js·全栈
爱吃红星柚1 天前
【学习】Elpis 抽离与发布 npm 包
前端·前端框架·node.js
梦帮科技1 天前
Next.js 16 模块化单体实战:App Router、领域模块与 Route Handler 分层
css·数据结构·链表·正则表达式·node.js·json·html5
梦帮科技1 天前
从 Guest 到 Platinum:Prompt 配额、API Key 与访问控制的安全闭环
javascript·git·架构·node.js·reactjs·html5·visual studio