【问题标题】:Using django select_for_update without rolling back on error使用 django select_for_update 不回滚错误
【发布时间】:2017-08-13 09:35:00
【问题描述】:

我正在尝试通过使用 select_for_update 实用程序来利用 django 的行级锁定。根据文档,这只能在 transaction.atomic 块内使用。使用transaction.atomic 块的副作用是,如果我的代码抛出异常,所有数据库更改都会回滚。我的用例是这样的,我实际上希望保留数据库更改,并允许传播异常。这让我的代码看起来像这样:

with transaction.atomic():
    user = User.objects.select_for_update.get(id=1234)
    try:
        user.do_something()
    except Exception as e:
        exception = e
    else:
        exception = None

if exception is not None:
    raise exception

这感觉完全是反模式,我敢肯定我一定遗漏了一些东西。我知道我可能会通过手动使用transaction.set_autocommit 来管理事务来推出我自己的解决方案,但我认为会有一种更简单的方法来获得此功能。有没有一种内置的方式来实现我想要的?

【问题讨论】:

    标签: django transactions database-locking


    【解决方案1】:

    我最终选择了如下所示的东西:

    from django.db import transaction
    
    class ErrorTolerantTransaction(transaction.Atomic):
    
        def __exit__(self, exc_type, exc_value, traceback):
            return super().__exit__(None, None, None)
    
    
    def error_tolerant_transaction(using=None, savepoint=True):
        """
        Wraps a code block in an 'error tolerant' transaction block to allow the use of
        select_for_update but without the effect of automatic rollback on exception.
    
        Can be invoked as either a decorator or context manager.
        """
        if callable(using):
            return ErrorTolerantTransaction('default', savepoint)(using)
    
        return ErrorTolerantTransaction(using, savepoint)
    

    我现在可以用error_tolerant_transaction 代替transaction.atomic,并且可以在不强制回滚的情况下引发异常。当然,与数据库相关的异常(即 IntegrityError)仍会导致回滚,但鉴于我们正在使用事务,这是预期的行为。作为奖励,此解决方案与 transaction.atomic 兼容,这意味着它可以嵌套在 atomic 块内,反之亦然。

    【讨论】:

    • 遇到了和你一样的问题,经过几个小时的搜索......这是我找到的唯一解决方案。尽管select_for_update 需要有一个明确定义的事务周期,但如果该事务通过异常退出,有些人不希望遭受回滚的影响。 transaction.atomic 应该定义一个事务周期,并让用户选择是否应该在异常时提交这些更改。
    猜你喜欢
    • 2014-10-16
    • 2014-08-05
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 2023-03-24
    • 2018-08-03
    相关资源
    最近更新 更多