SQLAlchemy 嵌套事务的解决方案
sqlachemy 是python的orm框架,在使用一段时间后,我们通常会出现事务嵌套的情况,看到很多人写代码的时候,居然是session到处传递,这无疑是加大了代码之间的耦合度。
案例:
def save(session):
# TODO def update(session):
# TODO def service():
session = getSession();
try:
save(session);
update(session);
session.commit();
except Exception as e:
session.rollback();
finally:
if not session:
session.close(); 假设save和update是同一个事务,但是上述的实践缺强制了save和update的 session相耦合来达成,好的实践应该是:save和update无任何关系,只是在实现业务逻辑时,组合到一个事务,确保事务性即可,即: def service():
try:
save();
update();
except Exception as e:
# TODO
因此如何解决这个问题是本文需要阐述的主题。
解决方案是:
ACID是事务的四个基本特征,通常我们的理解事务是一个操作单元,要么一起成功要么一起失败(原子性);通过一个例子来直接说明如何解决的。
场景:注册用户(添加一个用户,会未用户送10个积分)
创建表
create table user(
id int not null auto_increment,
name varchar(255) not null default '' comment '用户名',
created_at datetime not null default current_timestamp comment '创建时间',
updated_at datetime not null default current_timestamp comment '更新时间',
primary key (`id`)
)engine innodb charset=utf8 comment '用户表'; create table user_credits(
id int not null auto_increment,
user_id int not null default 0 comment '用户ID',
user_name varchar(255) not null default '' comment '用户名',
score int not null default 0 comment '积分',
created_at datetime not null default current_timestamp comment '创建时间',
updated_at datetime not null default current_timestamp comment '更新时间',
primary key (`id`),
unique key `uk_user_id` (`user_id`)
)engine innodb charset=utf8 comment '用户积分表';
sqlalchemy 实现
# -*- coding:utf-8 -*- import datetime
from sqlalchemy import create_engine, Column, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session engine = create_engine("mysql+pymysql://root:root@localhost:3306/csdn", echo=True) # 必须使用scoped_session,域session可以将session进行共享
DBSession = scoped_session(sessionmaker(bind=engine)) BaseModel = declarative_base() # ----------- Relation Model Object---------------- # class User(BaseModel): __tablename__ = "user" id = Column(Integer, primary_key=True)
name = Column(String)
created_at = Column(DateTime, default=datetime.datetime.now)
updated_at = Column(DateTime, default=datetime.datetime.now) class UserCredits(BaseModel): __tablename__ = "user_credits" id = Column(Integer, primary_key=True)
user_id = Column(Integer)
user_name = Column(String)
score = Column(Integer)
created_at = Column(DateTime, default=datetime.datetime.now)
updated_at = Column(DateTime, default=datetime.datetime.now) # ----------- Service implements---------------- # def add_user(user):
" 添加用户 "
session = DBSession()
try:
session.add(user)
session.commit()
except Exception as e:
session.rollback()
print("AddUser: ======={}=======".format(e))
finally:
if not session:
session.close() def add_user_credits(userCredits, interrupt=True):
" 添加用户积分记录 "
session = DBSession()
try:
if interrupt:
raise Exception("--- interrupt ---") session.add(userCredits)
session.commit()
except Exception as e:
session.rollback()
print("AddUserCredits: ======={}=======".format(e))
finally:
if not session:
session.close() def regist_user(): session = DBSession()
try:
# 开启子事务
session.begin(subtransactions=True) # TODO Service
user = User(name='wangzhiping')
add_user(user)
add_user_credits(UserCredits(
user_id=user.id,
user_name=user.name,
score=10
), False) session.commit()
except Exception as e:
session.rollback()
print("AddUserCredits: ======={}=======".format(e))
finally:
if not session:
session.close() # ---------- exec -----------
regist_user()
1,设置session时,需要指定为scoped_session,目的是session可以共享(ThreadLocal);
2,session.begin(subtransactions=True) 开启子事务管理;
这是实际上regist_user是在同一个线程中的session,这是add_user,add_user_credits实际上session是同一个,所以可以实现。其实这个可以更进一步扩展,把事务隔离级别,传播属性,这里不做介绍 ---------------------
作者:紫守笨
来源:CSDN
原文:https://blog.csdn.net/program_red/article/details/55194130?utm_source=copy
版权声明:本文为博主原创文章,转载请附上博文链接!
转载:https://blog.csdn.net/program_red/article/details/55194130
SQLAlchemy 嵌套事务的解决方案的更多相关文章
- 一个非侵入的Go事务管理库——工作原理
在上一篇文章"一个非侵入的Go事务管理库--如何使用"中,我讲述了如何使用事务库.有些读者可能读过"清晰架构(Clean Architecture)的Go微服务: 事物管 ...
- sqlalchemy中文乱码问题解决方案
本文参考http://firefish.blog.51cto.com/298258/112794/的解决方案 问题: 本文在Ubuntu上利用scrapy抓取数据写入mysql数据库时,用到sqlal ...
- PHP中实现MySQL嵌套事务的两种解决方案
PHP中实现MySQL嵌套事务的两种解决方案 一.问题起源 在MySQL的官方文档中有明确的说明不支持嵌套事务: Transactions cannot be nested. This is a co ...
- sqlalchemy 查询结果转json个人解决方案
参考了网上很多资料,自己搞了一个适合的 在model 内增加一个函数: class User(db.Model): __tablename__ = 'user' userid = db.Column( ...
- 脱离 Spring 实现复杂嵌套事务,之一(必要的概念)
事务传播行为种类 Spring在TransactionDefinition接口中规定了7种类型的事务传播行为, 它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播: 表1事务传播行为类型 事务 ...
- flask-sqlalchemy分表解决方案
转自:http://ju.outofmemory.cn/entry/61448 关键词: flask-sqlalchemy, sqlalchemy, 分表,分库 大型系统.海量数据肯定涉及到分库分表这 ...
- 【事务】<查询不到同一调用方法其它事务提交的更新>解决方案
最近遇到一个很棘手的问题,至今也解释不清楚原因,不过已经找到了解决方案. 先来看看Propagation属性的值含义,@Transactional中Propagation属性有7个选项可供选择: Pr ...
- svn 集成 redmine 账户验证的终极解决方案
svn 集成 redmine 账户验证的终极解决方案 赖勇浩(http://laiyonghao.com) 动机 对于大部分开发团队来说,一般都需要一套 SCM 系统,通常是 svn + redmin ...
- Memcache,redis,rabbitMQ,SQLAlchemy
Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...
随机推荐
- C#通过窗体属性缩小一定尺寸时,无法再缩小窗体尺寸问题
问题:通过窗体属性缩小窗体尺寸时,发现改变到一定大小时无法再缩小.条件:在代码中设置窗体的尺寸由窗体属性里设置的宽高决定,但实际通过窗体属性设置窗体大小,一定大小时无法再缩小,那是因为我们没有把窗体属 ...
- pdf.js插件使用记录,在线打开pdf
天记录一个js库:pdf.js.主要是实现在线打开pdf功能.因为项目需求需要能在线查看pdf文档,所以就研究了一下这个控件. 有些人很好奇,在线打开pdf文档浏览器不是支持吗.是的你说的都是现代浏览 ...
- php截取中文字符串无乱码的方法
利用php内置方法mb_substr截取中文不乱码,使用起来非常简单 <?php $str = '我喜欢laravel or yii2'; echo mb_substr($str, 0, 1, ...
- virtualbox中 Kali Linux安装增强功能
1. 将VBoxLinuxAdditions.run文件copy出来 2. 赋予执行权限 chmod +x VBoxLinuxAdditions.run 3. 安装 ./VBoxLinuxAdditi ...
- [HTML/CSS]三角形
CSS盒子模型 当我们把padding和width,height全部设置为0,border设为一个较大的像素时 即:我们需要什么方向的三角形,只需把其余的三角形背景色设置为transparent:
- Sublime Text 2 2.0.2 序列号
----- BEGIN LICENSE -----Andrew WeberSingle User LicenseEA7E-855605813A03DD 5E4AD9E6 6C0EEB94 BC9979 ...
- 苹果手机如何投屏到win10电脑上
苹果手机中的IOS系统比安卓系统的确好用.苹果手机使用多久都不会出现手机卡顿的现象,一如既往的流畅自如,这就是人们追求苹果机的原因之一.苹果手机朋友们可能会觉得手机屏幕太小影响视觉怎么办,苹果手机如何 ...
- python 标准类库-数据类型之集合-容器数据类型
标准类库-数据类型之集合-容器数据类型 by:授客 QQ:1033553122 Counter对象 例子 >>> from collections import Counter ...
- C# RichTextBox 制作文本编辑器
本文利用一个简单的小例子[文本编辑器],讲解RichTextBox的用法,仅供学习分享使用,如有不足之处,还请指正. Windows窗体中的RichTextBox控件用于显示,输入和操作格式化的文本, ...
- Android为TV端助力 Intent匹配action,category和data原则
1.当你在androidmanifest里面定义了一个或多个action时 你使用隐式意图其他activity或者service时,规定你隐式里面的action必须匹配XML中定义的action,可以 ...