回滚原理 Since database connections are thread-local, this is thread-safe.
mysql django
实践:
django @transaction.atomic 机制分析
1、数据库清空表Tab
2、请求django-view
@transaction.atomic(using=settings.TRANSACTION_DEFAULT_USING)
def post(self, request):
serializer = self.serializer_class(data=request.data)
i = Tab.objects.all()
print(i[0])
raise False
'''
控制台输出
(0.003) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.003) SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; args=None
'''
结果可以打印一条db数据
3、最终数据库表仍为空
猜想:
在session中,设置隔离级别为“读提交的”,注意,这里的“提交的”是指其他会话“提交的”,而该会话本身的“未提交”的是在该会话中可以读到的;
@transaction.atomic(using=settings.TRANSACTION_DEFAULT_USING)
def atomic(using=None, savepoint=True):
# Bare decorator: @atomic -- although the first argument is called
# `using`, it's actually the function being decorated.
if callable(using):
return Atomic(DEFAULT_DB_ALIAS, savepoint)(using)
# Decorator: @atomic(...) or context manager: with atomic(...): ...
else:
return Atomic(using, savepoint)
#################################
# Decorators / context managers #
#################################
class Atomic(ContextDecorator):
"""
Guarantee the atomic execution of a given block.
An instance can be used either as a decorator or as a context manager.
When it's used as a decorator, __call__ wraps the execution of the
decorated function in the instance itself, used as a context manager.
When it's used as a context manager, __enter__ creates a transaction or a
savepoint, depending on whether a transaction is already in progress, and
__exit__ commits the transaction or releases the savepoint on normal exit,
and rolls back the transaction or to the savepoint on exceptions.
It's possible to disable the creation of savepoints if the goal is to
ensure that some code runs within a transaction without creating overhead.
A stack of savepoints identifiers is maintained as an attribute of the
connection. None denotes the absence of a savepoint.
This allows reentrancy even if the same AtomicWrapper is reused. For
example, it's possible to define `oa = atomic('other')` and use `@oa` or
`with oa:` multiple times.
Since database connections are thread-local, this is thread-safe.
This is a private API.
"""
def __init__(self, using, savepoint):
self.using = using
self.savepoint = savepoint
def __enter__(self):
connection = get_connection(self.using)
if not connection.in_atomic_block:
# Reset state when entering an outermost atomic block.
connection.commit_on_exit = True
connection.needs_rollback = False
if not connection.get_autocommit():
# sqlite3 in Python < 3.6 doesn't handle transactions and
# savepoints properly when autocommit is off.
# Turning autocommit back on isn't an option; it would trigger
# a premature commit. Give up if that happens.
if connection.features.autocommits_when_autocommit_is_off:
raise TransactionManagementError(
"Your database backend doesn't behave properly when "
"autocommit is off. Turn it on before using 'atomic'.")
# Pretend we're already in an atomic block to bypass the code
# that disables autocommit to enter a transaction, and make a
# note to deal with this case in __exit__.
connection.in_atomic_block = True
connection.commit_on_exit = False
if connection.in_atomic_block:
# We're already in a transaction; create a savepoint, unless we
# were told not to or we're already waiting for a rollback. The
# second condition avoids creating useless savepoints and prevents
# overwriting needs_rollback until the rollback is performed.
if self.savepoint and not connection.needs_rollback:
sid = connection.savepoint()
connection.savepoint_ids.append(sid)
else:
connection.savepoint_ids.append(None)
else:
connection.set_autocommit(False, force_begin_transaction_with_broken_autocommit=True)
connection.in_atomic_block = True
def __exit__(self, exc_type, exc_value, traceback):
connection = get_connection(self.using)
if connection.savepoint_ids:
sid = connection.savepoint_ids.pop()
else:
# Prematurely unset this flag to allow using commit or rollback.
connection.in_atomic_block = False
try:
if connection.closed_in_transaction:
# The database will perform a rollback by itself.
# Wait until we exit the outermost block.
pass
elif exc_type is None and not connection.needs_rollback:
if connection.in_atomic_block:
# Release savepoint if there is one
if sid is not None:
try:
connection.savepoint_commit(sid)
except DatabaseError:
try:
connection.savepoint_rollback(sid)
# The savepoint won't be reused. Release it to
# minimize overhead for the database server.
connection.savepoint_commit(sid)
except Error:
# If rolling back to a savepoint fails, mark for
# rollback at a higher level and avoid shadowing
# the original exception.
connection.needs_rollback = True
raise
else:
# Commit transaction
try:
connection.commit()
except DatabaseError:
try:
connection.rollback()
except Error:
# An error during rollback means that something
# went wrong with the connection. Drop it.
connection.close()
raise
else:
# This flag will be set to True again if there isn't a savepoint
# allowing to perform the rollback at this level.
connection.needs_rollback = False
if connection.in_atomic_block:
# Roll back to savepoint if there is one, mark for rollback
# otherwise.
if sid is None:
connection.needs_rollback = True
else:
try:
connection.savepoint_rollback(sid)
# The savepoint won't be reused. Release it to
# minimize overhead for the database server.
connection.savepoint_commit(sid)
except Error:
# If rolling back to a savepoint fails, mark for
# rollback at a higher level and avoid shadowing
# the original exception.
connection.needs_rollback = True
else:
# Roll back transaction
try:
connection.rollback()
except Error:
# An error during rollback means that something
# went wrong with the connection. Drop it.
connection.close()
finally:
# Outermost block exit when autocommit was enabled.
if not connection.in_atomic_block:
if connection.closed_in_transaction:
connection.connection = None
else:
connection.set_autocommit(True)
# Outermost block exit when autocommit was disabled.
elif not connection.savepoint_ids and not connection.commit_on_exit:
if connection.closed_in_transaction:
connection.connection = None
else:
connection.in_atomic_block = False
def atomic(using=None, savepoint=True):
# Bare decorator: @atomic -- although the first argument is called
# `using`, it's actually the function being decorated.
if callable(using):
return Atomic(DEFAULT_DB_ALIAS, savepoint)(using)
# Decorator: @atomic(...) or context manager: with atomic(...): ...
else:
return Atomic(using, savepoint)
def atomic(using=None, savepoint=True):
# Bare decorator: @atomic -- although the first argument is called
# `using`, it's actually the function being decorated.
if callable(using):
return Atomic(DEFAULT_DB_ALIAS, savepoint)(using)
# Decorator: @atomic(...) or context manager: with atomic(...): ...
else:
return Atomic(using, savepoint)
Database transactions | Django documentation | Django https://docs.djangoproject.com/en/3.0/topics/db/transactions/atomicblocks can be nested. In this case, when an inner block completes successfully, its effects can still be rolled back if an exception is raised in the outer block at a later point.
回滚原理 Since database connections are thread-local, this is thread-safe.的更多相关文章
- Spring事务管理——回滚(rollback-for)控制
探讨Spring事务控制中,异常触发事务回滚原理.文章进行了6种情况下的Spring事务是否回滚. 以下代码都是基于Spring与Mybatis整合,使用Spring声明式事务配置事务方法. 1.不捕 ...
- ssh事务回滚,纪念这几个月困扰已久的心酸
以前的事务采用的是JTA,xml注入的方式.本人就着开发要优雅合理利用轮子的态度,一直不满意JTA式的申明和切入方式. spring的注解方式多优雅,可是万恶的直到项目快要上线时终于找到了注解式不能回 ...
- Jenkins:参数化构建:分支|模块|回滚|打印日志
@ 目录 多分支 安装Git Parameter Plug-In 配置参数 选择构建分支 分模块 前提 分模块build 参数配置 分模块shell脚本 mvn 的基本用法 分模块运行 Jenkins ...
- Java Thread Local – How to use and code sample(转)
转载自:https://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/ Thread Local ...
- 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理
[微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...
- Oracle-11g-R2(11.2.0.3.x)RAC Oracle Grid & Database 零宕机方式回滚 PSU(自动模式)
回滚环境: 1.源库版本: Grid Infrastructure:11.2.0.3.15 Database:11.2.0.3.15 2.目标库版本: Grid Infrastructure:11.2 ...
- 难道你还不知道Spring之事务的回滚和提交的原理吗,这篇文章带你走进源码级别的解读。
上一篇文章讲解了获取事务,并通过获取的connection设置只读,隔离级别等:这篇文章讲事务剩下的回滚和提交. 事务的回滚处理 之前已经完成了目标方法运行前的事务准备工作.而这些准备工作的最大目的无 ...
- C#中回滚TransactionScope的使用方法和原理
TransactionScope只要一个操作失败,它会自动回滚,Complete表示事务完成 实事上,一个错误的理解就是Complete()方法是提交事务的,这是错误的,事实上,它的作用的表示本事 ...
- 【转载】C#中回滚TransactionScope的使用方法和原理
TransactionScope只要一个操作失败,它会自动回滚,Complete表示事务完成 实事上,一个错误的理解就是Complete()方法是提交事务的,这是错误的,事实上,它的作用的表示本事务完 ...
随机推荐
- 【命令】glances命令和dstat命令
https://www.cnblogs.com/l75790/articles/9197829.html 文章里面的进程和作业管理篇
- (五)cp命令复制文件或者目录
一.cp的含义.功能及命令格式 cp(英文copy的缩写)命令可以将一个文件或者目录从一个位置复制到另外一个位置.cp的功能就是将一个文件复制成 一个指定的目的文件或者复制到一个指定的目录中,兼具复制 ...
- python序列(一)列表的增加
列表是python中内置有序可变序列,列表的所有元素放在一堆中括号"{}"中,并使用逗号隔开 1.列表的创建 使用"="直接创建一个列表 >>> ...
- [leetcode]75.Sort Color三指针
import java.util.Arrays; /** * Given an array with n objects colored red,white or blue, * sort them ...
- Redis 设计与实现 8:五大数据类型之哈希
哈希对象的编码有两种:ziplist.hashtable. 编码一:ziplist ziplist 已经是我们的老朋友了,它一出现,那肯定就是为了节省内存啦.那么哈希对象是怎么用 ziplist 存储 ...
- linux系统重启后提示An error occurred during the file system check.
一.问题描述 生产环境中一台浪潮NF8480M3外观红灯报警,鉴于无法登陆带外管理口,只能对服务器进行断电重启操作 二.问题现象 重启后进入开机过程并报错,正常来说进入此界面后直接输入root密码即可 ...
- Docker PHP 扩展配置
# PHP 容器配置 # 从官方基础版本构建 FROM php:7.2-fpm # 官方版本默认安装扩展: # Core, ctype, curl # date, dom # fileinfo, fi ...
- VMware 16.1虚拟机安装
VMware 16.1创建虚拟机 1.1首先打开我们安装好的VMware点击创建新的虚拟机 典型为自动安装,接口位默认 自定义安装更自由,可以把按需求选择 VMware16版本,只能选择Worksta ...
- 【C++】《C++ Primer 》第四章
第四章 表达式 一.基础 重载运算符:当运算符作用在类类型的运算对象时,用户可以自行定义其含义. 左值和右值: C中:左值可以在表达式左边,右值不能. C++中:当一个对象被用作右值的时候,用的是对象 ...
- Flutter 布局类组件:线性布局(Row和Column)
前言 所谓线性布局,即指沿水平或垂直方向排布子组件.Flutter中通过Row和Column来实现线性布局,并且它们都继承自弹性布局(Flex). 接口描述 Row({ Key key, // 表示子 ...