Django4.0 数据库事务-底层API

2022-03-16 17:38 更新

自动提交

Django 在 ​django.db.transaction​ 模块中提供了一个 API 来管理每个数据库连接的自动提交状态。

get_autocommit(using=None)

set_autocommit(autocommit, using=None)

这些函数使接受一个 ​using ​参数表示所要操作的数据库。如果未提供,则 Django 使用 "​default​" 数据库。
自动提交默认为开启,如果你将它关闭,自己承担后果。
一旦你关闭了自动提交, Django 将无法帮助你,数据库将会按照你使用的数据库适配器的默认行为进行操作。
在关闭自动提交之前,你必须确保当前没有活动的事务,通常你可以执行 ​commit()​ 或者 ​rollback()​ 函数以达到该条件。
当一个原子 ​atomic()​ 事务处于活动状态时, Django 将会拒绝关闭自动提交的请求,因为这样会破坏原子性。

事务

事务是指具有原子性的一系列数据库操作。即使你的程序崩溃,数据库也会确保这些操作要么全部完成要么全部都未执行。

Django 不提供启动事务的 API。 启动事务的预期方法是使用 ​set_autocommit()​ 禁用自动提交。

进入事务后,你可以选择在 ​commit()​ 之前应用执行的更改,或者使用 ​rollback()​ 取消它们。这些函数在 ​django.db.transaction​ 中定义。

commit(using=None)

rollback(using=None)

这些函数使接受一个 ​using ​参数表示所要操作的数据库。如果未提供,则 Django 使用 "​default​" 数据库。
当一个原子 ​atomic()​ 事务处于活动状态时, Django 将会拒绝进行事务提交或者事务回滚,因为这样会破坏原子性。

保存点

保存点在事务中是标记物,它可以使得回滚部分事务,而不是所有事务。 SQLite, PostgreSQL, Oracle, 和 MySQL (当使用 InnoDB 存储引擎) 后端提供了保存点。其他后端提供了保存点函数,但它们是空操作——它们实际上没有做任何事情。
如果你正在使用 Django 的默认行为——自动提交,保存点并不特别有用。尽管,一旦你用 ​atomic() ​打开了一个事务,那么需要构建一系列的等待提交或回滚的数据库操作。如果发出回滚,那么会回滚整个事务。保存点有能力执行颗粒度级别的回滚,而不是由 ​transaction.rollback()​ 执行的完全回滚。
当嵌套了 ​atomic()​ 装饰器,它会创建一个保存点来允许部分提交或回滚。强烈推荐只使用 ​atomic()​ 而不是下面描述的函数,但它们仍然是公共 API 的一部分,而且没计划要弃用它们。
这里的每一个函数使用 ​using ​参数,这个参数为应用的数据库名。如果没有 ​using ​参数,那么会使用 "​default​" 数据库。
保存点由 ​django.db.transaction​中的三个函数来控制:

savepoint(using=None)

创建新的保存点。这标志着事务中已知处于“良好”状态的一个点。返回保存点ID (​sid​) 。

savepoint_commit(sid, using=None)

释放保存点 ​sid ​。自保存点被创建依赖执行的更改成为事务的一部分。

savepoint_rollback(sid, using=None)

回滚事务来保存 ​sid ​。

如果不支持保存点或数据库在自动模式时,这些函数不执行操作。

另外,还有一个实用功能:

clean_savepoints(using=None)

重置用于生成唯一保存点ID的计数器。

下面的例子演示保存点的用法:

from django.db import transaction

# open a transaction
@transaction.atomic
def viewfunc(request):

    a.save()
    # transaction now contains a.save()

    sid = transaction.savepoint()

    b.save()
    # transaction now contains a.save() and b.save()

    if want_to_keep_b:
        transaction.savepoint_commit(sid)
        # open transaction still contains a.save() and b.save()
    else:
        transaction.savepoint_rollback(sid)
        # open transaction now contains only a.save()

保存点可能通过执行部分回滚来恢复数据库错误。如果你在 ​atomic()​ 块中执行此操作,那么整个块将仍然被回滚,因为它不知道你已经处理了较低级别的情况。为了防止发生,你可以使用下面的函数控制回滚行为。

get_rollback(using=None)

set_rollback(rollback, using=None)

当存在内部原子块时,设置回滚标记为 ​True ​将强制回滚。这对于触发回滚而不引发异常可能很有用。
将它设置为 ​False ​会防止这样的回滚。在这样做之前,确保你已经将事务回滚到当前原子块中一个正常的保存点。否则你会破坏原子性并且可能发生数据损坏。


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号