数据库连接池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.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中的数据插入,结果会发现,所有线程中的数据全部被插入。

参考:

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

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
要使用SQLAlchemy连接多个数据库并使用连接池,你可以创建多个连接池对象并为每个数据库创建一个独立的引擎。以下是一个示例代码,展示了如何使用SQLAlchemy连接池连接多个MySQL数据库: ```python from sqlalchemy import create_engine from sqlalchemy.pool import QueuePool # 创建连接池1 pool1 = QueuePool( creator=lambda: mysql.connector.connect( host='localhost', database='database1', user='username1', password='password1' ), pool_size=5 ) # 创建连接池2 pool2 = QueuePool( creator=lambda: mysql.connector.connect( host='localhost', database='database2', user='username2', password='password2' ), pool_size=5 ) # 创建SQLAlchemy引擎1 engine1 = create_engine('mysql+mysqlconnector://', creator=pool1.get) # 创建SQLAlchemy引擎2 engine2 = create_engine('mysql+mysqlconnector://', creator=pool2.get) # 将DataFrame写入数据库1的表 df.to_sql(name='table1', con=engine1, if_exists='replace', index=False) # 将DataFrame写入数据库2的表 df.to_sql(name='table2', con=engine2, if_exists='replace', index=False) ``` 在上面的代码中,你需要将`database1`、`username1`、`password1`替换为第一个数据库的实际信息,将`database2`、`username2`、`password2`替换为第二个数据库的实际信息。 通过创建多个连接池对象和引擎对象,你可以连接多个MySQL数据库,并使用连接池管理数据库连接。 希望这可以满足你的需求!如果还有其他问题,请随提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值