【问题标题】:ZODB: To where transaction.savepoint writes data?ZODB:transaction.savepoint 将数据写入到哪里?
【发布时间】:2013-11-01 00:30:34
【问题描述】:

根据ZODB documentation

保存点允许数据管理器在不提交完整事务的情况下将工作保存到其存储中。" "保存点还有助于释放内存,否则这些内存将用于保持事务的整个状态。

根据很有启发性的文章When to commit data in ZODB(Martijn Pieters):

...在整个交易过程中,您可以要求将数据临时存储在磁盘上。 [...]
保存点所做的一件事是调用 ZODB 缓存的垃圾收集,这意味着当前未使用的所有数据都将从内存中删除。

问题是,我需要在一个事务中存储很多项目,如下所示:

for i, item in enumerate(aLotOfItems):
    database[i]=item
    if i % 10000 ==0:
        transaction.savepoint(True)
transaction.commit()

我有点期望 transaction.savepoint 的工作方式与 bsddb3.db.Db.sync 相同。当Db.sync()被调用时,数据库被刷新,你可以观察它。但是当设置了保存点时,显然数据库和 tmp 文件都不会增长或改变大小,直到transaction.commit()

我真的很困惑:

  • 设置保存点后实际发生了什么?

  • 它与提交/刷新数据库有何不同?

  • 如果是“数据暂存到磁盘”,savepoint将数据写入到哪里?

  • 我可以依靠保存点来真正“释放内存”吗?

【问题讨论】:

    标签: python transactions zodb


    【解决方案1】:

    保存点最初的主要用途是能够回滚事务的部分

    假设你想接受大量的日志条目,但需要将它们批量处理到数据库中:

    for batch in per_batch(log_entries):
        sp = transaction.savepoint()
        try:
            process_batch(batch)
        except BatchFailedException:
            sp.rollback()
            transaction.commit()
            raise
    

    现在事务已经提交,除了最后一批已经回滚。

    这就是使用保存点的原始原因。设置保存点具有触发 ZODB 缓存垃圾收集运行的副作用。

    ZODB 保存最近访问的对象的缓存。这包括在当前事务中实际上没有改变的对象;您只是从数据库中检索它们,使用它们的数据,然后停止直接引用它们。 ZODB 存储一个对象图;一个对象引用其他对象,而后者又引用其他对象。这些对象中的每一个,如果它们从Persistent 基类继承,它们都是单独的 ZODB 记录。当你遍历图时,这些对象都被加载到内存中。

    GC 再次从内存中运行清除它们,前提是它们没有改变。再次遍历对象图会再次将它们加载到内存中,但在保存点期间清除它们可以节省内存。

    保存点数据本身存储在磁盘上的TmpStorage 文件中,位于您的TEMP 目录中。这使用了一个tempfile.TemporaryFile() 对象,出于安全原因,它以unlinked 状态创建;该文件存在,但目录条目在创建时立即被清除。因此,您无法从 ZODB 进程之外查看此文件。

    完全提交将数据移动到实际的 ZODB 数据库中并完成事务。

    【讨论】:

    • 感谢您的大力帮助。我可以这样理解吗:保存点的工作就像 --- 如果已知现有记录已更改,则它会保留在缓存中,除非我乐观地认为永远不会回滚;如果这条记录没有改变,它会从缓存中清除吗?当我调用 cacheMinimize() 时,它会做同样的事情吗?而且,如果我想在文件中创建一个 rcord 而不是内存,那么我还不如使用 ZODB 以外的东西,对吧?
    • cacheMinimize() 进行一次扫描,cacheGC() 进行多次扫描;后者是保存点时使用的。在您提交事务之前,ZODB FileStorage 不会改变。
    【解决方案2】:

    保存点的主要用途是释放内存并将与事务相关的数据从内存存储到磁盘 - 特别是在处理大型事务和大量修改数据时。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多