使用 SQLAlchemy 会话解决烧瓶和并发问题
Using SQLAlchemy sessions with flask & concurrency problems
我正在使用 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,所以我自己在我的 flask 应用程序中实现了 SQLAlchemy,但我不确定如何使用会话.
这是我在 __ 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在多个客户端发出请求时不起作用,好像每个客户端都共享同一个会话。
我应该如何实现会话以便每个客户端都有不同的会话并且可以同时发出请求?
谢谢。
您似乎希望多个 HTTP 请求共享一个事务。这是不可能的 - 与 HTTP 的无状态性质不兼容。
例如,请考虑一个客户端将打开事务但无法关闭它,因为它已失去连接。服务器无法知道它并且会永远打开此事务,可能会阻止其他客户端。
使用事务来捆绑数据库请求是合理的,例如当存在多个写操作时出于性能原因。或者保持数据库一致。但它始终必须在打开的同一个 HTTP 请求上提交或回滚。
我知道这是一个老话题,但你可以用 djondb(没有SQL 数据库)实现这个,
使用 djondb 你可以创建事务,如果出现问题,即你失去了连接,没关系,事务可以永远存在而不会影响性能,也不会创建锁,djondb 已被设计为支持 long -term 事务,因此您可以打开事务、使用它、提交它、回滚它或只是丢弃它(关闭连接并忘记它在那里)并且它不会使数据库处于任何不一致的状态。
我知道这对于 Relational 人来说可能听起来很奇怪,但这就是 NoSQL 的美妙之处,它创造了新的范例来支持 SQL 人所说的不可能。
希望对您有所帮助,
我正在使用 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,所以我自己在我的 flask 应用程序中实现了 SQLAlchemy,但我不确定如何使用会话.
这是我在 __ 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在多个客户端发出请求时不起作用,好像每个客户端都共享同一个会话。
我应该如何实现会话以便每个客户端都有不同的会话并且可以同时发出请求?
谢谢。
您似乎希望多个 HTTP 请求共享一个事务。这是不可能的 - 与 HTTP 的无状态性质不兼容。
例如,请考虑一个客户端将打开事务但无法关闭它,因为它已失去连接。服务器无法知道它并且会永远打开此事务,可能会阻止其他客户端。
使用事务来捆绑数据库请求是合理的,例如当存在多个写操作时出于性能原因。或者保持数据库一致。但它始终必须在打开的同一个 HTTP 请求上提交或回滚。
我知道这是一个老话题,但你可以用 djondb(没有SQL 数据库)实现这个,
使用 djondb 你可以创建事务,如果出现问题,即你失去了连接,没关系,事务可以永远存在而不会影响性能,也不会创建锁,djondb 已被设计为支持 long -term 事务,因此您可以打开事务、使用它、提交它、回滚它或只是丢弃它(关闭连接并忘记它在那里)并且它不会使数据库处于任何不一致的状态。
我知道这对于 Relational 人来说可能听起来很奇怪,但这就是 NoSQL 的美妙之处,它创造了新的范例来支持 SQL 人所说的不可能。
希望对您有所帮助,