当前位置: 代码迷 >> 综合 >> sqlalchemy多线程使用,threadlocal
  详细解决方案

sqlalchemy多线程使用,threadlocal

热度:29   发布时间:2024-01-21 03:40:53.0

问题

tornado中使用sqlalchemy遇到一个问题,接口在并发的时候,sqlalchemy会报各种错误。

解决办法

原因是sqlalchemy用sessionmaker直接建立的session本身就不是线程安全的,怎么保证线程安全呢,一般官方推荐用scoped_session有范围的session,来封装

class scoped_session(object):def __init__(self, session_factory, scopefunc=None):self.session_factory = session_factoryif scopefunc:self.registry = ScopedRegistry(session_factory, scopefunc)else:self.registry = ThreadLocalRegistry(session_factory)def __call__(self, **kw):if kw:if self.registry.has():raise sa_exc.InvalidRequestError("Scoped session is already present; ""no new arguments may be specified.")else:sess = self.session_factory(**kw)self.registry.set(sess)return sesselse:return self.registry()def remove(self):if self.registry.has():self.registry().close()self.registry.clear()

scoped_session包裹了原来的sessionmaker,实例化了一个TreadLocalRegistry对象,scoped_session()调用__call__ -> self.registry() -> TreadLocalRegistry.__call__方法,

先从本地线程取出value,如果异常则用sessionmaker创建一个session,并放在这个线程变量里面,同一个线程进来则使用同一个session

class ThreadLocalRegistry(ScopedRegistry):"""A :class:`.ScopedRegistry` that uses a ``threading.local()``variable for storage."""def __init__(self, createfunc):self.createfunc = createfuncself.registry = threading.local()def __call__(self):try:return self.registry.valueexcept AttributeError:val = self.registry.value = self.createfunc()return valdef has(self):return hasattr(self.registry, "value")d
  相关解决方案