flask-security:减少数据库访问次数

5 投票
2 回答
1132 浏览
提问于 2025-04-18 13:07

在我的应用程序中,我使用了 flask-security 来处理用户的登录和权限管理。同时,我还用到了 SQLAlchemy 来管理数据,后端是 MySQL。这个应用运行得很好。

然后,我对 MySQL 进行了监控,发现每次在应用中请求一个网址时,flask-security 库都会发送两个数据库查询:

  • select ... from user where user.id = '用户标识'
  • select ... from role, roles_users ...

我觉得这可能会影响性能,所以想要减少这些查询。我不太确定是不是有什么配置我没有注意到。

2 个回答

0

一个选择是重写 Flask-Login 的 user_loader。不过,看看 这个讨论,了解为什么在每次请求时加载用户信息通常是必要的。

这是 Flask-Security 实现 user_loader 的方式。

def _user_loader(user_id):
    return _security.datastore.find_user(id=user_id)

这最终会生成一个 SQL 查询。

为了后续参考,这里有关于如何启用 sqlalchemy 发出的 SQL 查询的跟踪(调试)的方法:

import logging
logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)

另一种解决方案,可能有点复杂,就是为用户和角色设置一个单独的 SQL-lite 数据库(用于 Flask-Login、Flask-Security 等)。在这种情况下,读取的延迟几乎为零。

1

在不考虑进一步优化的情况下(比如使用Redis来缓存SQL的响应或用户对象),我认为你无法避免第一次请求。在大多数情况下,你需要用户的数据,而你又不想把这些数据存储在用户的会话cookie里。你可以考虑使用像Redis这样的工具,把这些信息存储在服务器端,并通过会话ID来索引。

不过,你可以尝试使用JOIN来避免第二次请求。通过同时进行第一次和第二次请求,可以节省一些传输时间,而且数据库也能选择一个合适的查询计划。

撰写回答