【问题标题】:Flask-SQLAlchemy session object not seeing changes to the database?Flask-SQLAlchemy 会话对象看不到数据库的更改?
【发布时间】:2019-02-08 21:50:34
【问题描述】:

我在 PythonAnywhere 上有一个网站,它使用 Flask 和 Flask-SQLAlchemy 连接到 MySQL 数据库。用户可以使用该网站将保存到数据库中的任务作为表中的记录进行排队,然后一个单独的计划任务(Python 程序)检查数据库并处理每条未处理的记录。

我遇到的问题是计划任务的db查询似乎只在第一次运行时才找到新记录,但如果我随后使用网站添加新任务,仍在运行的计划任务重复出现db 查询(每 5 秒)似乎没有检测到新记录。

对这里可能发生的事情有什么想法吗?

这是 bash 文件运行的代码:

def generate_any_pending_videos():
    unfinished_videos = db.session.query(Video)\
                                  .filter(~Video.status.has(VideoStatus.status.in_(['Error', 'Finished', 'Video deleted'])))\
                                  .order_by(Video.datetime_created)\
                                  .all()
    for video in unfinished_videos:
        try:
            logging.info("Attempting to create video for video %d" % video.id)
            generate_video(video)
        except Exception as e:
            logging.error(str(e))


if __name__ == '__main__':
    while True:
        generate_any_pending_videos()
        time.sleep(5)

【问题讨论】:

  • 你确定服务器的数据库连接已经持久化了更改(即事务已经提交),你确定计划任务的数据库会话刷新而不是对缓存对象进行操作吗?
  • 我使用 MySQL Workbench 来确认新记录正在被持久化,我不确定第二点,事实上这就是我怀疑发生的事情,但我不确定如果这就是会话的工作方式。如果有办法刷新会话可以解决我的问题。
  • 尝试打开一个新会话,或者看看这个问题:stackoverflow.com/questions/19143345/…
  • 你能提供你的代码(或者更好,一个最小的工作示例)吗?如果不看看你在做什么,就很难提供帮助。
  • @jorgeh 我已经添加了正在运行的代码的本质。请注意,“db”对象是来自我的 Flask 服务器的 SQLAlchemy(app) Flask-SQLAlchemy 对象,我不确定这是否会有所不同。

标签: python mysql flask flask-sqlalchemy pythonanywhere


【解决方案1】:

找到了解决方法:由于某种原因,在我的查询显示新记录之前运行 db.session.commit()

if __name__ == '__main__':
    while True:
        generate_any_pending_videos()
        time.sleep(5)
        db.session.commit()  # For some reason this is needed to be able to detect newly-created videos

【讨论】:

  • 嗯...... Flask 应该将 SQLAlchemy 会话绑定到请求事务,并且当生成响应时,事务应该提交并与它一起提交数据库会话。如果不是这种情况,我建议检查请求处理和数据库会话处理,以确保数据正确持久化。
  • 如果 InnoDB 在非锁定 SELECT 返回结果时提交,则(默认)隔离级别 REPEATABLE READ 将没有任何意义。 @MiguelGarcia 的回答是正确的。只要您不在 REPEATABLE READ 中提交(或回滚)事务,其中的所有查询都将从第一个查询创建的快照中读取,以后对数据库的更改将对您的事务/会话保持透明。
  • 这对我有用!!!应该是正确的答案。另一种方法是在 server.cnf 中设置[mysqld] transaction-isolation=READ-COMMITTED
  • 天啊,你不知道我已经搜索了多少并试图找到解决这个问题的方法。谢谢你的帖子!
【解决方案2】:

默认情况下,所有 SqlAlchemy 查询都在事务内运行 http://docs.sqlalchemy.org/en/latest/orm/session_transaction.html 。这就是您仅在脚本的第一次调用中获取新数据的原因。因为在一个事务里面看到的数据不会改变,也就是ACID中的I,事务是隔离的。 在提交或回滚之后,下一个查询会启动一个新事务,因此您将从数据库中获取新数据。

【讨论】:

    【解决方案3】:

    您可以在 sqlalchemy 引擎中更改隔离级别:

    engine = create_engine(db_path, execution_options={"isolation_level": "READ COMMITTED"})
    

    这是mysql默认配置的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-26
      • 1970-01-01
      • 1970-01-01
      • 2014-11-30
      • 2020-04-03
      • 1970-01-01
      • 2020-02-17
      相关资源
      最近更新 更多