Django事务使用
做DRF项目的时候遇到了一个问题:一次请求,要同时在数据库里的三张表里创建字段,且三个字段存在相互依赖关系(B的字段里有A的pk键值),且其中任何一个字段校验失败,三张表都要撤回写入。折腾了老半天,在学长提醒用Django事务去解决的时候,才意识的这个操作应该要符合原子性
数据库事务
看DJango文档
https://docs.djangoproject.com/zh-hans/3.2/topics/db/transactions/
完美契合需求
Django 提供了一个 API 控制数据库事务。
-
atomic
(using=None, savepoint=True, durable=False)¶原子性是数据库事务的定义属性。
atomic
允许创建代码块来保证数据库的原子性。如果代码块成功创建,这个变动会提交到数据库。如果有异常,变动会回滚。
要避免在 atomic
内部捕捉异常!
当存在 atomic
块时, Django 查看它是否正常退出或存在异常来决定是提交还是正常回滚。如果你在 atomic
内部捕捉并且处理异常,你可以对 Django 隐藏问题代码。这会导致一些意外的行为。
打开事务会对数据库服务器有性能成本。尽量减少这种开销,要保持事务尽可能简短
提交后
哎,当时没看到,使用On_commit的话,代码效率还可以更高
但貌似这样的话,就不好撤销更改了
如果使用块中有异常抛出,所有在事务内的操作都会被撤销
保存点在事务中是标记物,它可以使得回滚部分乌市(机器翻译错误?),而不是所有事务。 SQLite, PostgreSQL, Oracle, 和 MySQL (当使用 InnoDB 存储引擎) 后端提供了保存点
-
savepoint
(using=None)¶创建新的保存点。这标志着事务中已知处于“良好”状态的一个点。返回保存点ID (
sid
) 。 -
savepoint_commit
(sid, using=None)¶释放保存点
sid
。自保存点被创建依赖执行的更改成为事务的一部分。
使用上述的两条就可以完成任务了,是不是很简单
我自己的实现:
https://github.com/wheel-w/bk-c-course/pull/40
ORM还是强,毕竟不同数据库保存点的使用都不一样,但ORM全部都统一了起来