使用sqlalchemy延迟更改

时间:2014-01-14 09:20:41

标签: python sqlite sqlalchemy cherrypy

我在多进程环境中面临一种奇怪的行为。

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

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

我在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()),但P2 (web app)P3 (cmd line process)相比,实时看不到更改。 P2可能需要几秒钟才能完成更改......

有什么想法吗?

非常感谢,

皮尔

1 个答案:

答案 0 :(得分:0)

发现了这个问题。 根据SQLAlchemy文档,必须在每个Web请求之后调用Session.remove()。

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

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)

现在工作正常。

HTH其他人,

皮尔