Multithreading 使用同步函数时跨线程共享SQLAlchemy会话的FastAPI

Multithreading 使用同步函数时跨线程共享SQLAlchemy会话的FastAPI,multithreading,sqlalchemy,fastapi,Multithreading,Sqlalchemy,Fastapi,关于正常的defpath操作函数、依赖项和SQLAlchemy的Noob问题。引用这里的示例:,其中数据库会话在get_db()(同步)中创建,并在create_user()(同步)中使用。根据,同步依赖项和路径操作函数在一个线程池中执行,那么这是否意味着相同的DB会话对象在两个不同的线程之间有效共享(假设在依赖项和路径操作函数中重复使用的不是同一个线程)?由于SQLAlchemy会话不是线程安全的,这可能会有问题吗 我可能完全误解了这是如何工作的,因此任何澄清都将不胜感激 谢谢 编辑:仔细考虑

关于正常的
def
path操作函数、依赖项和SQLAlchemy的Noob问题。引用这里的示例:,其中数据库会话在
get_db()
(同步)中创建,并在
create_user()
(同步)中使用。根据,同步依赖项和路径操作函数在一个线程池中执行,那么这是否意味着相同的DB会话对象在两个不同的线程之间有效共享(假设在依赖项和路径操作函数中重复使用的不是同一个线程)?由于SQLAlchemy会话不是线程安全的,这可能会有问题吗

我可能完全误解了这是如何工作的,因此任何澄清都将不胜感激

谢谢

编辑:仔细考虑后,我认为这应该没问题,因为会话是按顺序(而不是同时)访问的,即使它可能由两个不同的线程访问。但是我假设像下面这样使用
会话
会有问题吗

async def func(s: Session):
  loop = asyncio.get_running_loop()
  await loop.run_in_executor(None, some_func, s)
  await loop.run_in_executor(None, some_other_func, s)
  ...

是的,会话对象不是线程安全的,但在SQLAlchemy中,您实际上有多个连接,因为SQLAlchemy有一个连接池系统,所以您定义的每个其他会话本地都有自己的连接

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()
因此,不共享任何连接,所有内容都是分离的,并且在请求之后会话本地关闭。所以它不是线程安全的,但我认为它不会有问题


假设您有一个端点,它同时收到2个请求,因此在本例中,不同的连接将响应您的请求。即使它不是并发的,它的行为也与池并行。

谢谢您的回答!因此,我遇到的问题并不是一个会话是否由两个请求共享(正如你上面解释的,不是),而是一个会话是否由处理同一请求的两个线程共享(我认为它们是共享的,但应该可以,因为访问是顺序的)。@ljiatu Ups,我认为会很好地解释这些事情,如果不行,我会再尽力:)是的,我以前读过,所以我认为这意味着我在问题末尾的例子是不安全的,对吗?没错,如果你想线程安全会话签出
范围会话