数据库连接池SQLAlchemy中多线程安全的问题

1、数据库模块model.py

from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker
session_factory = sessionmaker(bind=some_engine)
Session = scoped_session(session_factory)

2、业务模块thread.py

import threading
from model import Session class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(20))
fullname = Column(String(20))
password = Column(String(20))
age = Column(Integer) class MyThread(threading.Thread): def __init__(self, threadName):
super(MyThread, self).__init__()
self.name = threading.current_thread().name def run(self):
session = Session() #每个线程都可以直接使用数据库模块定义的Session,执行时,每一个session都相当于一个connection
session.query(User).all()
user = User(name="hawk-%s"%self.name, fullname="xxxx",password="xxxx",age=10)
session.add(user)
time.sleep(1)
if self.name == "thread-9":
session.commit()
Session.remove() if __name__ == "__main__":
arr = []
for i in xrange(10):
arr.append(MyThread('thread-%s' % i))
for i in arr:
i.start()
for i in arr:
i.join()

错误示范:

class MyThread(threading.Thread):

    def __init__(self, threadName):
super(MyThread, self).__init__()
self.session = Session() #错误!
self.name = threading.current_thread().name def run(self):
self.session.query(User).all()
user = User(name="hawk-%s"%self.name, fullname="xxxx",password="xxxx",age=10)
self.session.add(user)
time.sleep(1)
if self.name == "thread-9":
self.session.commit()
Session.remove()

错误解析:
看了SQLAlchemy之后源码发现,Session() 返回的是一个threading.local()对象的成员变量,threading.local()对象只有在线程内部才能实现线程隔离,因此只能放在run()函数里,而不能作为类成员变量。

如果按照错误示例来运行,所有线程其实公用了一个session,没有做到线程隔离,session.commit()操作会互相影响,我们原本只想将thread-9中的数据插入,结果会发现,所有线程中的数据全部被插入。

 如何避免使用SQLAlchemy使用连接池

在使用 create_engine创建引擎时,如果默认不指定连接池设置的话,一般情况下,SQLAlchemy会使用一个 QueuePool绑定在新创建的引擎上。并附上合适的连接池参数。

在以默认的方法create_engine时(如下),就会创建一个带连接池的引擎。

engine = create_engine('postgresql://postgres@127.0.0.1/dbname')
在这种情况下,当你使用了session后就算显式地调用session.close(),也不能把连接关闭。连接会由QueuePool连接池进行管理并复用。

这种特性在一般情况下并不会有问题,不过当数据库服务器因为一些原因进行了重启的话。最初保持的数据库连接就失效了。随后进行的session.query()等方法就会抛出异常导致程序出错。

如果想禁用SQLAlchemy提供的数据库连接池,只需要在调用create_engine是指定连接池为NullPool,SQLAlchemy就会在执行session.close()后立刻断开数据库连接。当然,如果session对象被析构但是没有被调用session.close(),则数据库连接不会被断开,直到程序终止。

下面的代码就可以避免SQLAlchemy使用连接池:

#!/usr/bin/env python
#-*- coding: utf-8 -*- from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import NullPool engine = create_engine('postgresql://postgres@127.0.0.1/dbname',
poolclass=NullPool)
Session = sessionmaker(bind=engine)
session = Session()
usr_obj_list = session.query(UsrObj).all()
print usr_obj_list[0].id
session.close()

https://blog.csdn.net/daijiguo/article/details/79486294

https://blog.csdn.net/weiwangchao_/article/details/80185009

参考:

https://www.cnblogs.com/1a2a/p/8278698.html 
http://blog.csdn.net/kikaylee/article/details/53232920

LT和ET模式的更多相关文章

  1. 【原】谈谈对Objective-C中代理模式的误解

    [原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...

  2. 彻底理解AC多模式匹配算法

    (本文尤其适合遍览网上的讲解而仍百思不得姐的同学) 一.原理 AC自动机首先将模式组记录为Trie字典树的形式,以节点表示不同状态,边上标以字母表中的字符,表示状态的转移.根节点状态记为0状态,表示起 ...

  3. 制作类似ThinkPHP框架中的PATHINFO模式功能

    一.PATHINFO功能简述 搞PHP的都知道ThinkPHP是一个免费开源的轻量级PHP框架,虽说轻量但它的功能却很强大.这也是我接触学习的第一个框架.TP框架中的URL默认模式即是PathInfo ...

  4. MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息

    MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二 ...

  5. MVVM模式解析和在WPF中的实现(五)View和ViewModel的通信

    MVVM模式解析和在WPF中的实现(五) View和ViewModel的通信 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 M ...

  6. MVVM模式解析和在WPF中的实现(三)命令绑定

    MVVM模式解析和在WPF中的实现(三) 命令绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  7. MVVM模式和在WPF中的实现(二)数据绑定

    MVVM模式解析和在WPF中的实现(二) 数据绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  8. MVVM模式和在WPF中的实现(一)MVVM模式简介

    MVVM模式解析和在WPF中的实现(一) MVVM模式简介 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在 ...

  9. Microservice架构模式简介

    在2014年,Sam Newman,Martin Fowler在ThoughtWorks的一位同事,出版了一本新书<Building Microservices>.该书描述了如何按照Mic ...

  10. 工厂方法模式——创建型模式02

    1. 简单工厂模式     在介绍工厂方法模式之前,先介绍一下简单工厂模式.虽然简单工厂模式不属于GoF 23种设计模式,但通常将它作为学习其他工厂模式的入门,并且在实际开发中使用的也较为频繁. (1 ...

随机推荐

  1. linux 的空命令:(冒号)

    php里面又“空操作”这个东西,于是想一想linux的命令中是否有“空命令”这种东西,搜索一下,结果发现真的有这个东西存在 -------:) 冒号 : 就是空命令.即什么也不做,是一个命令占位符 # ...

  2. 超棒的HTML5/CSS3单页面响应式模板(支持Bootstrap)

    在线演示 使用Bootstrap实现的响应式单页面模板. 桌面效果: 移动设备效果: 阅读全文:超棒的HTML5/CSS3单页面响应式模板(支持Bootstrap)

  3. 从头学习MVC4基础之视图

    实例一:首先简单显示实例: 控制器代码: public class WujyTestController : Controller { public ActionResult Index() { Li ...

  4. react-keeper

    通过 react-keeper 替换掉 react-router 解决 页面缓存问题.

  5. postgresql-slony-I同步复制配置步骤

    主数据库: 172.16.254.21 端口:5432 从数据库: 172.16.254.22 端口:5432 步骤1:主从均安装slon apt-get install slon-bin 步骤2:主 ...

  6. 转:sock_ev——linux平台socket事件框架(基于数据报的测试程序) .

    上一篇已经做过注释,这一篇直接上代码 /******************************************************************************** ...

  7. 【APP接口开发】常用HTTP响应头状态码详解

    1.200 OK,客户端请求城成功 2.400 Bad Request ,客服端请求语法错误,服务器无法理解和处理 3.401 unauthorized,请求未通过认证 4.403 permissio ...

  8. 中文latex参考文献格式

    中文latex参考文献格式 原来英文: \begin{thebibliography}{1} \bibitem{Ben-Shimon2015RecSys} D.~Ben-Shimon, A.~Tsik ...

  9. JavaScript:使用JavaScript 实现注册表单的校验

    说明:在点击提交时进行表单校验,具体要求如下: 1)用户名为3~16个字符,且不能包含”@”和”#”字符: 2)密码和校验密码必须一致,且长度在8个字符到16个字符: 3)兴趣爱好至少选择一项: 4) ...

  10. 和求余运算巧妙结合的jns指令

    .text:004A78B1  and eax, 80000001h.text:004A78B6  jns short loc_4A78BD.text:004A78B8 dec eax.text:00 ...