如何解决flask-security + SQLAlchemy:在无效事务回滚之前无法重新连接
编辑:
环境:
Python 3.8.3
Flask==1.1.2
Flask-Login==0.5.0
Flask-Security==3.0.0
sqlAlchemy==1.3.19
我是flask-security和sqlAlchemy的新手。我参考了flask-security的文档,然后尝试以下方法:
engine = create_engine(
db_source,encoding="utf-8",pool_size=64,pool_timeout=300,pool_recycle=3,max_overflow=64
)
db_session = scoped_session(
sessionmaker(
autocommit=False,autoflush=False,bind=engine
)
)
Base = declarative_base()
Base.query = db_session.query_property()
# some codes define the classes Role and User for flask-security
user_datastore = sqlAlchemySessionUserDatastore(
db_session,User,Role
)
security = Security(app,user_datastore)
.
.
.
@app.route("/test/",methods=["GET","POST"])
@login_required
def api_test():
# do something
在开始时,flask-security内置登录页面和登录过程开始运行。但是,一段时间后,登录过程将获得“内部服务器错误”,并且日志显示“ sqlalchemy.exc.StatementError:(sqlalchemy.exc.InvalidRequestError)在无效事务回滚之前无法重新连接”。
我搜索了一些类似的问题,他们说我需要做这样的事情以进行回滚:
try:
# this is where the "work" happens!
yield session
# always commit changes!
session.commit()
except:
# if any kind of exception occurs,rollback transaction
session.rollback()
raise
finally:
session.close()
但是,我所有的代码都不会在任何地方调用session.commit()
,所以我不确定session.rollback()
的放置位置。
我的问题是:
- 如果
session.rollback()
有帮助,即使我没有在代码中调用session.commit()
,该如何放置? - 我猜这是烧瓶安全性内在的东西吗?如果是,该如何解决?
- 问题可能出在我错误地使用了
scoped_session
吗?scoped_session
不会回滚/删除自身吗?
编辑:
感谢@jwag,我将尽力更准确地描述问题。
- 首先,我在服务器上启动该应用程序。目前,登录过程运行良好。
- 但是,过一段时间(这意味着“此”应用程序至少在一天之内再也不会连接到数据库,但实际上我不确定问题何时开始出现)。发生“直到无效的事务被回滚之前才重新连接”的问题。
- 还有另一个应用程序通过MysqL.connector连接到其他表的同一数据库。即使我的应用程序遇到“在无效交易回滚之前也无法重新连接”的问题,该应用程序始终运行良好。该问题一直持续到我重新启动httpd服务。
我的问题似乎与此问题非常相似:
SQLAlchemy: Can't reconnect until invalid transaction is rolled back
唯一的区别是我不仅使用sqlAlchemy,而且还使用flask-security,所以我什至不知道在哪里回滚/关闭会话-甚至问题不同,但我不知道。
我认为问题不在于用户/角色模型(错误消息并不指向这些模型),但是无论如何我在下面显示了它们。
class RolesUsers(Base):
__tablename__ = "roles_users"
__table_args__ = {
"MysqL_engine": "InnoDB","MysqL_charset": "utf8mb4"
}
id = Column(Integer(),primary_key=True)
user_id = Column("user_id",Integer(),ForeignKey("user.id"))
role_id = Column("role_id",ForeignKey("role.id"))
class Role(Base,RoleMixin):
__tablename__ = "role"
__table_args__ = {
"MysqL_engine": "InnoDB",primary_key=True)
name = Column(String(20),unique=True)
description = Column(String(128))
class User(Base,UserMixin):
__tablename__ = "user"
__table_args__ = {
"MysqL_engine": "InnoDB","MysqL_charset": "utf8mb4"
}
id = Column(Integer,primary_key=True)
email = Column(String(128),unique=True)
username = Column(String(128))
password = Column(String(128))
last_login_at = Column(DateTime())
current_login_at = Column(DateTime())
last_login_ip = Column(String(100))
current_login_ip = Column(String(100))
login_count = Column(Integer)
active = Column(Boolean())
roles = relationship(
"Role",secondary="roles_users",backref=backref("users",lazy="dynamic")
)
解决方法
您没有说您使用的是什么版本的Flask-Security。一般而言-实际的解决方案是弄清楚为什么会收到“无效语句错误”并进行修复。不尝试回滚。根据您的后端数据库(您是否使用pycopg2?),我发现如果尝试使用不正确的类型进行SELECT(例如,该列是一个int且您传递了一个字符串),它将引发这种错误。
在代码段中,您定义了“ db_session”,但您将查询定义为“ backstage_db_session”?
最后-当您说“一段时间后”并且“您不提交”时-是否意味着您的应用程序永远不会读取或写入数据库?
最后,如果需要更多帮助,请提供用户模型代码。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。