回滚原理 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()方法是提交事务的,这是错误的,事实上,它的作用的表示本事务完 ...
随机推荐
- 微信小程序--相对路径和绝对路径
相对路径: ../表示返回访问上一级目录 如:../../components/like/index 绝对路径: 以"/"开头 表示从根目录开始寻找文件 如:/components ...
- JAVA多线程下高并发的处理经验
java中的线程:java中,每个线程都有一个调用栈存放在线程栈之中,一个java应用总是从main()函数开始运行,被称为主线程.一旦创建一个新的线程,就会产生一个线程栈.线程总体分为:用户线程和守 ...
- java代理(静态代理和jdk动态代理以及cglib代理)
版权声明:本文为Fighter168原创文章,未经允许不得转载. 目录(?)[+] 说到代理,脑袋中浮现一大堆代理相关的名词,代理模式,静态代理,jdk代理,cglib代理等等. 记忆特别深刻 ...
- 浅谈IAT加密原理及过程
上一次做完代码段加密后,又接触到了新的加密方式:IAT加密 IAT加密是通过隐藏程序的导入表信息,以达到增加分析程序的难度.因为没有导入表,就无法单纯的从静态状态下分析调用了什么函数,动态调试时,也无 ...
- WIN10系统下静态编译Qt4.8.7
qt-everywhere-opensource-src-4.8.7.tar.gz http://download.qt.io/archive/qt/4.8/4.8.7/qt-everywhere- ...
- 这一次,彻底理解XSS攻击
希望读完本文大家彻底理解XSS攻击,如果读完本文还不清楚,我请你吃饭慢慢告诉你~ 话不多说,我们进入正题. 一.简述 跨站脚本(Cross-site scripting,简称为:CSS, 但这会与层叠 ...
- TurtleBot3使用课程-第一节a(北京智能佳)
目录 1.ROS设置(远程PC) 2 1.1 ROS安装和设置 2 1.1.1 设置source.list 2 1.1.2 键设置 2 1.1.3 ROS安装 2 1.1.4安装包构建的依赖关系 2 ...
- 移动端学习之理解WEB APP、Native APP、Hybrid APP以及React Native/uniapp包括H5、小程序等的区别与共通之处
因为工作需要,需要进一步了解移动端的开发,遂返回复习移动端的知识点,在开始学习之前,产生了疑惑WEB APP .Native APP .Hybrid APP.React Native.Uniapp.H ...
- java集合并发操作异常解决方法:CopyOnWriteArrayList
一.我们知道ArrayList是线程不安全的,请编写一个不安全的案例并给出解决方案 HashSet与ArrayList一致 HashMap HashSet底层是一个HashMap,存储的值放在Hash ...
- 关于echarts中的noDataLoadingOption——loading动画的问题
在最近的一个项目中用到echarts这个插件,其中关于noDataLoadingOption配置项的问题让我困惑了好长时间.经过蛋疼的查找下,终于搞明白是版本的原因. 且看官网的介绍:ECharts, ...