【发布时间】:2021-02-06 03:33:00
【问题描述】:
编辑:
环境:
Python 3.8.3
Flask==1.1.2
Flask-Login==0.5.0
Flask-Security==3.0.0
SQLAlchemy==1.3.19
数据库是 MySQL 5.6.45,InnoDB 表。
我是 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", Integer(), ForeignKey("role.id"))
class Role(Base, RoleMixin):
__tablename__ = "role"
__table_args__ = {
"mysql_engine": "InnoDB",
"mysql_charset": "utf8mb4"
}
id = Column(Integer(), 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")
)
【问题讨论】:
标签: python sqlalchemy flask-security