2013-10-31 16 views
1

ZODB documentationZODB:要将transaction.savepoint写入数据的位置?

保存点允许数据管理器保存工作,它的存储没有提交完整的交易“,“保存点也对,否则将被用来保持整个国家的可用内存有用。交易。

按照很有启发性的文章When to commit data in ZODB(马亭皮特斯):

...整个交易在那里,你可以要求数据能够暂时存储在磁盘中的一个点。 [...]
保存点所做的一件事就是调用ZODB缓存的垃圾回收,这意味着任何当前未使用的数据都会从内存中移除。

的事情是,我需要很多的项目存储在一个事务中,这样的事情:

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

我kindof预计transaction.savepoint以相同的方式工作为bsddb3.db.Db.sync。当调用Db.sync()时,数据库将被刷新,您可以观察它。但是,当设置保存点时,显然数据库和tmp文件都不会增长或变化,直到transaction.commit()

我真的很困惑:

  • 时的保存点被设置什么是实际发生的?

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

  • 如果“要临时存储在磁盘上的数据”,保存点写入数据的位置在哪里?

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

回答

7

保存点的原始主要用途是能够回滚交易的零件

说你要接受大量的日志条目,但需要分批处理这些到数据库:

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

现在交易已经提交,除了最后一批已经铺开背部。

那是原始使用保存点的原因。设置保存点具有触发ZODB缓存garbagecollection运行的副作用。

ZODB拥有最近访问的对象缓存。这包括在当前事务期间实际上不会改变的对象;您只是从数据库中检索它们,使用它们的数据,然后直接停止引用它们。 ZODB存储一个对象图;一个对象引用其他对象,该对象又引用其他对象。每个这些对象(如果它们继承自基类Persistent)都是独立的ZODB记录。遍历图时,这些对象全部加载到内存中。

GC运行从内存中清除了,只要它们没有变化。再次遍历对象图将再次将它们加载到内存中,但在保存点期间清除它们可节省内存。

保存点数据本身存储在TmpStorage文件的磁盘中,在您的TEMP目录中。这使用了一个tempfile.TemporaryFile()对象,该对象出于安全原因在未链接的状态中创建;该文件存在,但目录条目在创建时立即清除。您因此不能从ZODB进程外部看到此文件。

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

+0

谢谢你的巨大帮助。我是否可以通过这种方式理解它:保存点的工作就像---如果已知的现有记录已更改,它将保留在缓存中,除非我乐观地认为永不回滚;如果这条记录没有改变,它会从缓存中清除?当我调用cacheMinimize()时,它是否做同样的事情?如果我想在文件创建时使用rcord而不是内存,我不妨使用ZODB以外的东西,对吧? – DingZh

+0

'cacheMinimize()'做一次扫描,'cacheGC()'做多次扫描;后者是保存点时使用的。直到您提交事务后,ZODB FileStorage才会更改。 –

0

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