使用SQLAlchemy会话处理flask和并发问题

2024-09-28 01:28:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用Flask和SQLAlchemy开发一个API,我想做的是:

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

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

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

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

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

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

因为我不想使用自动回滚,所以我不能真正使用flask SQLAlchemy,所以我自己在flask应用程序中实现SQLAlchemy,但是我不确定如何使用会话。在

下面是我在\uuinit\uuuy.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就不起作用了,似乎每个客户机都共享同一个会话。在

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

谢谢。在


Tags: 对象gtidfalse客户端newclosereturn
2条回答

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

例如,请考虑一个客户机将打开事务并无法关闭它,因为它已失去连接。一个服务器无法知道它,并且会永远打开这个事务,可能会阻塞其他客户机。在

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

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

有了djondb,您可以创建事务,如果出现问题,例如,您失去了连接,这无关紧要,事务可以一直存在,而不会影响性能,也不会创建锁,djondb已被用于支持长期事务,因此您可以打开事务、使用事务、提交事务,回滚或丢弃它(关闭连接并忘记它在那里),它不会使数据库处于任何不一致的状态。在

我知道这对关系型的人来说可能听起来很奇怪,但这正是NoSQL的优点,它创建了新的范例来支持SQL人员所说的不可能。在

希望这有帮助

相关问题 更多 >

    热门问题