跳至内容

交互式事务

警告

事务尚未针对 CockroachDB 进行全面测试。

Prisma Client Python 支持交互式事务,这是一种通用的解决方案,允许您将多个操作作为单个原子操作运行 - 如果任何操作失败,或在事务期间引发任何其他错误,Prisma 将回滚整个事务。

这与 批量查询 不同,因为您可以执行依赖于先前操作结果的操作。

用法

可以使用 Prisma.tx() 方法创建事务,该方法返回一个上下文管理器,当进入时返回一个单独的 Prisma 实例,该实例将所有查询包装在事务中。

from prisma import Prisma

prisma = Prisma()
await prisma.connect()

async with prisma.tx() as transaction:
    user = await transaction.user.update(
        where={'id': from_user_id},
        data={'balance': {'decrement': 50}}
    )
    if user.balance < 0:
        raise ValueError(f'{user.name} does not have enough balance')

    await transaction.user.update(
        where={'id': to_user_id},
        data={'balance': {'increment': 50}}
    )
from prisma import Prisma

prisma = Prisma()
prisma.connect()

with prisma.tx() as transaction:
    user = transaction.user.update(
        where={'id': from_user_id},
        data={'balance': {'decrement': 50}}
    )
    if user.balance < 0:
        raise ValueError(f'{user.name} does not have enough balance')

    transaction.user.update(
        where={'id': to_user_id},
        data={'balance': {'increment': 50}}
    )

在此示例中,如果引发了 ValueError,则整个事务将回滚。这意味着第一个 update 调用将被逆转。

如果此示例成功运行,则当上下文管理器退出时,两个数据库写入都将提交,这意味着在应用程序中其他地方运行的查询将访问更新后的数据。

与模型查询一起使用

警告

事务支持与 基于模型的查询 结合使用尚不稳定。

不要依赖 Model.prisma() 始终使用默认的 Prisma 实例。这在将来可能会更改。

from prisma import Prisma
from prisma.models import User

prisma = Prisma(auto_register=True)
await prisma.connect()

async with prisma.tx() as transaction:
    user = await User.prisma(transaction).update(
        where={'id': from_user_id},
        data={'balance': {'decrement': 50}}
    )
    if user.balance < 0:
        raise ValueError(f'{user.name} does not have enough balance')

    user = await User.prisma(transaction).update(
        where={'id': to_user_id},
        data={'balance': {'increment': 50}}
    )
prisma = Prisma()
prisma.connect()

with prisma.tx() as transaction:
    user = User.prisma(transaction).update(
        where={'id': from_user_id},
        data={'balance': {'decrement': 50}}
    )
    if user.balance < 0:
        raise ValueError(f'{user.name} does not have enough balance')

    user = User.prisma(transaction).update(
        where={'id': to_user_id},
        data={'balance': {'increment': 50}}
    )

超时

您可以传递以下选项来配置如何将超时应用于您的事务

max_wait - Prisma 从数据库获取事务的最大等待时间。默认值为 2 秒

timeout - 事务在被取消和回滚之前可以运行的最大时间。默认值为 5 秒

from datetime import timedelta

prisma.tx(
    max_wait=timedelta(seconds=2),
    timeout=timedelta(seconds=10),
)