Django中的事务

1 开启全局的事务

python 复制代码
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 使用mysql数据库
        'NAME': 'tracerbackend',  # 要连接的数据库
        'USER': 'root',  # 链接数据库的用于名
        'PASSWORD': '123456',  # 链接数据库的用于名
        'HOST': '192.168.1.200',  # mysql服务监听的ip
        'PORT': 3306,  # mysql服务监听的端口
        # 设置为True代表同一个http请求所对应的所有sql都放在一个事务中执行
        # (要么所有都成功,要么所有都失败),这是全局性的配置,如果要对某个
        # http请求放水(然后自定义事务),可以用non_atomic_requests修饰器
        'ATOMIC_REQUESTS': True,

    }
}

在Django中,'ATOMIC_REQUESTS': True 是一个数据库设置选项,它会在每个HTTP请求开始时自动开启一个数据库事务,并在请求结束时提交或回滚该事务。这提供了一种方便的方式来确保数据库操作的原子性,即要么全部成功,要么全部失败。

python 复制代码
# 设置中默认开启全局事务
def home(request):
    models.Module.objects.create(project_id=1, title="测试事务")
    1/0
    models.IssuesType.objects.create(project_id=1, title="测试事务")
    return render(request, "home.html")

在这个例子中,我们为默认的数据库连接设置了'ATOMIC_REQUESTS': True。这意味着每当Django处理一个HTTP请求时,它都会自动开启一个数据库事务。如果请求成功完成并且没有发生任何异常,那么事务会在请求结束时自动提交。如果请求期间发生了异常,那么事务会被回滚,从而撤销该请求所做的所有数据库更改。

python 复制代码
from django.db import transaction

# 局部禁用
@transaction.non_atomic_requests
def home(request):

    models.Module.objects.create(project_id=1, title="测试事务")
    1/0
    models.IssuesType.objects.create(project_id=1, title="测试事务")

    return render(request, "home.html")

注意事项

  • 性能 :虽然'ATOMIC_REQUESTS': True可以提供数据一致性的保证,但它也可能对性能产生影响。因为每个请求都在其自己的事务中运行,这可能会增加数据库的开销,特别是在高并发的场景中。因此,在决定使用此选项时,应该仔细评估项目的性能和一致性需求。
  • 长时间运行的请求 :对于长时间运行的请求(例如,需要处理大量数据的请求),使用'ATOMIC_REQUESTS': True可能会导致事务保持打开状态很长时间,这可能会增加锁定争用和数据库资源的使用。在这种情况下,可能需要考虑其他的事务管理策略。
  • 手动事务管理 :即使启用了'ATOMIC_REQUESTS': True,你仍然可以在需要时手动管理事务。Django的数据库API提供了用于开启、提交和回滚事务的函数和上下文管理器。这些工具允许你在需要时覆盖自动事务管理的行为。
  • 未生效: 如果配置全局事务未生效,有可能是数据库不支持如sqlite不支持事务、中间件对异常进行了捕获导致失效、视图函数局部禁用。

2 开启视图函数的事务

全局开启事务时,在高并发的请求时,对数据库的压力也挺大的,可以在视图函数中对某些重要的操作开启事务比如支付或订单之类的

python 复制代码
from django.db import transaction

@transaction.atomic
def home(request):

    models.Module.objects.create(project_id=1, title="测试事务")
    1/0
    models.IssuesType.objects.create(project_id=1, title="测试事务")

    return render(request, "home.html")

3 手动事务

我们知道MySQL的写数据时互斥锁,一个视图函数中如果耗时较长,并发请求时事务不及时提交时将会都卡在提交事务上,因此在并发并发高的场景时可以将事务的控制颗粒度设置更细些,手动在关键地方设置事务。

python 复制代码
from django.db import transaction


def home(request):
    models.Module.objects.create(project_id=1, title="测试事务前")
    with transaction.atomic():
        models.Module.objects.create(project_id=1, title="测试事务")
        1/0
        models.IssuesType.objects.create(project_id=1, title="测试事务")

    return render(request, "home.html")

4 事务保存点

有时候事务中出现异常,不希望事务中全部的操作都进行回滚,比如记录用户操作行为到数据库的数据我们希望进行回滚

python 复制代码
from django.db import transaction


def home(request):
    with transaction.atomic():
        models.Module.objects.create(project_id=1, title="操作事务日志记录到数据库")
        try:
            sid = transaction.savepoint()
            models.Module.objects.create(project_id=1, title="测试事务")
            1/0
            models.IssuesType.objects.create(project_id=1, title="测试事务")
        except:
            transaction.savepoint_rollback(sid)  # 回滚到保存点
    transaction.savepoint_commit(sid)
    return render(request, "home.html")

5 开启事务回调

有时候我们希望事务提交之后做一些额外操作,比如下发订单成功了,立马发送提醒用户。

python 复制代码
from django.db import transaction


def sen_msg():
    print("事务成功")


def home(request):
    try:
        with transaction.atomic():
            models.Module.objects.create(project_id=1, title="操作事务日志记录到数据库")
            models.Module.objects.create(project_id=1, title="测试事务")
            # 测试事务是否成功 1 成功执行on_commit 2 失败不执行
            # 1/0
            models.IssuesType.objects.create(project_id=1, title="测试事务")
            transaction.on_commit(sen_msg)
    except Exception:
        print("事务执行失败")
    return render(request, "home.html")
相关推荐
hi星尘3 小时前
深度解析:基于Python的微信小程序自动化操作实现
python·微信小程序·自动化
Doker 多克3 小时前
Django 缓存框架
python·缓存·django
raoxiaoya4 小时前
同时安装多个版本的golang
开发语言·后端·golang
miracletiger5 小时前
uv 新的包管理工具总结
linux·人工智能·python
我不会编程5555 小时前
Python Cookbook-6.10 保留对被绑定方法的引用且支持垃圾回收
开发语言·python
ʚɞ 短腿欧尼5 小时前
关系数据的可视化
python·pycharm·可视化·数据可视化·图表
考虑考虑6 小时前
go使用gorilla/websocket实现websocket
后端·程序员·go
李少兄6 小时前
解决Spring Boot多模块自动配置失效问题
java·spring boot·后端
noravinsc7 小时前
django admin 中更新表数据 之后再将数据返回管理界面
数据库·django·sqlite
Piper蛋窝7 小时前
Go 1.19 相比 Go 1.18 有哪些值得注意的改动?
后端