【问题标题】:Delayed change using sqlalchemy使用 sqlalchemy 延迟更改
【发布时间】:2014-01-14 09:20:40
【问题描述】:

我在多进程环境中遇到了一个奇怪的行为。

我的第一个进程(后来称为 P1)通过 sqa 写入 db。我的第二个进程(后来称为 P2)通过 sqa 从 db 读取。第二个进程是一个 Web 应用程序,它通过 ajax 调用请求最新数据。

当 P1 更新数据(写入)时,P2 不会立即看到更改(读取)。在实际看到数据库更改(issuing session.query(...)) 之前,它必须轮询几次。如果我运行另一个 P3 进程,我可以看到更改实际上是在 db 中完成的,但 P2(网络应用程序)不会立即看到它。

我在 Ubuntu 13.04 上运行 sqa 0.8.4 (underlying db: sqlite),我的网络应用基于 cherrypy framework (3.2.0)

我使用作用域会话来获取线程安全的会话对象,如 SQLAlchemy documentation

这是我所有进程都使用的 OrmManager 类:

class OrmManager:

    def  __init__(self, database, metadata, echo=False):
        self.database = database

        engine = create_engine('sqlite:///' + database,
                               echo=echo,
                               connect_args={'detect_types': sqlite3.PARSE_DECLTYPES|
                                              sqlite3.PARSE_COLNAMES},
                               native_datetime=True,
                               poolclass=NullPool,
                               convert_unicode=True
                           )

    metadata.create_all(engine)

    # this factory is thread safe: a session object is returned (always the same) to the
    # caller. If called from another thread, the returned session object will be different
    session_factory = sessionmaker(bind=engine, expire_on_commit=False)
    self.session = scoped_session(session_factory)

def get_session(self):

    session = self.session()
    return session

P1、P2 和 P3 实现 OrmManager 并使用返回的会话如下:

orm_mgr = OrmManager(database=<path/to/my/.sqlite/file>, metadata=METADATA)

session = orm_mgr.get_session()

# do some stuff here

session.commit()

我检查了 P1 代码。 (call to session.commit()) 已很好地提交了 db 更改,但与 P3 (cmd line process) 相比,P2 (web app) 无法实时看到更改。 P2 可能需要几秒钟才能获得更改...

有什么想法吗?

非常感谢,

皮埃尔

【问题讨论】:

    标签: python sqlite sqlalchemy cherrypy


    【解决方案1】:

    发现问题。 根据 SQLAlchemy 文档,每次 Web 请求后都必须调用 Session.remove()。

    我将以下代码添加到我的cherrypy 应用程序中:

    def on_end_request():
        """As mentioned in SQLAlchemy documentation,
        scoped_session .remove() method has to be called
        at the end of each request"""
    
        Session.remove()
    

    和:

    cherrypy.config.update({'tools.dbsession_close.on' : True})
    
    # As mentioned in SQLAlchemy documentation, call the .remove() method
    # of the scoped_session object at the end of each request
    cherrypy.tools.dbsession_close = cherrypy.Tool('on_end_request', on_end_request)
    

    现在工作正常。

    其他人,

    皮埃尔

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-13
      • 2016-05-09
      • 2018-04-06
      • 2012-08-30
      • 1970-01-01
      相关资源
      最近更新 更多