2013-10-31 26 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

保存點的主要用途是釋放內存並將事務相關的數據從內存存儲到磁盤 - 特別是對於大量事務和大量修改的數據。