使用SQLAlchemy会话与flask&并发问题

时间:2015-04-15 09:42:21

标签: python postgresql session flask sqlalchemy

我正在使用Flask和SQLAlchemy开发API,这就是我想要做的事情:

我有一个客户端应用程序,在多个平板电脑上工作,必须发送多个请求以向服务器添加内容。 但我不希望在每个API请求结束时使用自动回滚(使用flask-sqlalchemy的默认行为),因为数据的发送是通过多个请求完成的,就像在这个非常简单的示例中一样:

1。 beginTransaction /?id = transactionId - >为发出该请求的客户端打开一个新会话。 SessionManager.new_session()在下面的代码中。

2。 addObject /?id = objectAid - >将一个对象添加到PostGreSQL数据库并刷新

第3。 addObject /?id = objectBid - >将一个对象添加到PostGreSQL数据库并刷新

4。 commitTransaction /?id = transactionId - >提交自beginTransaction以来发生的事情。 SessionManager.commit()在下面的代码中。

这里的要点是,如果客户端应用程序在发送«commitTransaction»之前崩溃/丢失了连接,则不会将数据添加到服务器,从而防止服务器上的数据不完整。

由于我不想使用自动回滚,我不能真正使用flask-SQLAlchemy,所以我将自己的SQLAlchemy实现到我的烧瓶应用程序中,但我不确定如何使用这些会话。 / p>

这是我在__ init __.py中执行的实现:

db = create_engine('postgresql+psycopg2://admin:pwd@localhost/postgresqlddb',
                   pool_reset_on_return=False,
                   echo=True, pool_size=20, max_overflow=5)

Base = declarative_base()
metadata = Base.metadata
metadata.bind = db

# create a configured "Session" class
Session = scoped_session(sessionmaker(bind=db, autoflush=False))



class SessionManager(object):

    currentSession = Session()

    @staticmethod
    def new_session():
    #if a session is already opened by the client, close it
    #create a new session
        try:
            SessionManager.currentSession.rollback()
            SessionManager.currentSession.close()
        except Exception, e:
            print(e)

        SessionManager.currentSession = Session()
        return SessionManager.currentSession

    @staticmethod
    def flush():
        try:
            SessionManager.currentSession.flush()
            return True
        except Exception, e:
            print(e)
            SessionManager.currentSession.rollback()
            return False

    @staticmethod
    def commit():
    #commit and close the session
    #create a new session in case the client makes a single request without using beginTransaction/
        try:
            SessionManager.currentSession.commit()
            SessionManager.currentSession.close()
            SessionManager.currentSession = Session()
            return True
        except Exception, e:
            print(e)
            SessionManager.currentSession.rollback()
            SessionManager.currentSession.close()
            SessionManager.currentSession = Session()
            return False

但是现在当多个客户端发出请求时,API不起作用,似乎每个客户端共享同一个会话。

我应该如何实现会话,以便每个客户端具有不同的会话并可以同时发出请求?

谢谢。

2 个答案:

答案 0 :(得分:1)

您似乎想要多个HTTP请求来共享一个事务。这是不可能的 - 与HTTP的无状态特性不兼容。

请注意,例如,一个客户端会打开事务并因为失去连接而无法关闭它。服务器无法知道它并且会永远打开此事务,可能会阻止其他客户端。

使用事务捆绑数据库请求是合理的,例如出于性能原因,当有多个写操作时。或者保持数据库一致。但它始终必须在打开的相同HTTP请求上提交或回滚。

答案 1 :(得分:0)

我知道这是一个旧线程,但您可以使用djondb(NoSQL数据库)来实现这一点,

使用djondb你可以创建交易,如果出现问题,即你丢失了连接,没关系,交易可以永远存在而不会影响性能,或者创建锁,djondb已被用来支持长期事务,所以你可以打开事务,使用它,提交它,回滚它或者丢弃它(关闭连接并忘记它就在那里)并且它不会使数据库处于任何不一致的状态。

我知道这对于Relational人来说可能听起来很奇怪,但这就是NoSQL的美妙之处,它创造了支持SQL人员认为不可能的新范例。

希望这有帮助,