sqlalchemy多线程使用,threadlocal

问题

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

解决办法

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

class scoped_session(object):

    def __init__(self, session_factory, scopefunc=None):

        self.session_factory = session_factory

        if 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 sess
        else:
            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 = createfunc
        self.registry = threading.local()

    def __call__(self):
        try:
            return self.registry.value
        except AttributeError:
            val = self.registry.value = self.createfunc()
            return val

    def has(self):
        return hasattr(self.registry, "value")

    d

你可能感兴趣的:(共享,tornado,threadlocal,sqlalchemy)