SQLAlchemy不将Python池线程识别为独立进程
我正在尝试将我的单线程应用程序转换为使用SQLAlchemy数据库的多线程应用程序。我发现SQLAlchemy会话不是线程安全的。因此,我们需要使用作用域_会话工厂进行线程安全的数据库访问 下面是我的输入数据集SQLAlchemy不将Python池线程识别为独立进程,python,database,multithreading,sqlalchemy,Python,Database,Multithreading,Sqlalchemy,我正在尝试将我的单线程应用程序转换为使用SQLAlchemy数据库的多线程应用程序。我发现SQLAlchemy会话不是线程安全的。因此,我们需要使用作用域_会话工厂进行线程安全的数据库访问 下面是我的输入数据集 input_list = [data1, data2, data3, data4, data5] 单线程应用程序 from sqlalchemy.orm import sessionmaker, scoped_session Session = sessionmaker(bind=en
input_list = [data1, data2, data3, data4, data5]
单线程应用程序
from sqlalchemy.orm import sessionmaker, scoped_session
Session = sessionmaker(bind=engine_url)
for data in input_list:
def myfunction(data):
db_session = Session()
print(db_session)
# use db_session to query/store the data
from sqlalchemy.orm import sessionmaker, scoped_session
Session = scoped_session(sessionmaker(bind=engine_url))
def myfunction(data):
db_session = Session()
print(db_session)
# use db_session to query/store the data
def myfunction_parallel():
with ThreadPool(4) as pool:
output = pool.map(myfunction, input_list)
当我尝试将其转换为多线程应用程序时
from sqlalchemy.orm import sessionmaker, scoped_session
Session = sessionmaker(bind=engine_url)
for data in input_list:
def myfunction(data):
db_session = Session()
print(db_session)
# use db_session to query/store the data
from sqlalchemy.orm import sessionmaker, scoped_session
Session = scoped_session(sessionmaker(bind=engine_url))
def myfunction(data):
db_session = Session()
print(db_session)
# use db_session to query/store the data
def myfunction_parallel():
with ThreadPool(4) as pool:
output = pool.map(myfunction, input_list)
在多线程变体中,我将
db_session
作为同一个对象,但我的期望是应该为每个线程创建一个新的会话对象,并且会话应该不同?范围会话注册表为每个请求会话的线程注册会话。这使代码能够调用db\u session=session()
,并获取线程的预期会话
但是,当不再需要会话时,应用程序有责任通知会话注册表。应用程序通过调用Session.remove()
来执行此操作,如文档所示:
scoped_session.remove()方法首先在当前会话上调用session.close(),其效果是首先释放会话拥有的所有连接/事务资源,然后丢弃会话本身。这里的“释放”意味着连接被返回到它们的连接池,任何事务状态都被回滚,最终使用底层DBAPI连接的rollback()方法
此时,作用域_会话对象为“空”,再次调用时将创建一个新会话
此代码应按预期工作:
def myfunction(数据):
db_session=session()
打印(db_会话)
#使用db_会话查询/存储数据
Session.remove()
另外,如果在创建第二个会话之前创建和清理一个会话并执行线程,则四个不同的会话对象完全可能具有相同的对象ID。(对于会话所在的代码,这是完全可能的。只在这么短的范围内。)在创建会话和打印会话之间添加一个sleep(1)
,以强制线程在会话对象可以GCed(释放其对象ID)之前屈服,并查看您是否仍然获得相同的对象ID。