Din*_*gZh 1 python transactions zodb
根据ZODB文档:
保存点允许数据管理器将工作保存到其存储而无需提交完整事务.""保存点对释放内存也很有用,否则将用于保留事务的整个状态.
根据非常有启发性的文章何时在ZODB(Martijn Pieters)中提交数据:
...在整个交易过程中您可以要求将数据临时存储在磁盘上的一个点.[...]
保存点所做的一件事是调用ZODB缓存的垃圾收集,这意味着当前未使用的任何数据都将从内存中删除.
问题是,我需要在一个事务中存储大量项目,如下所示:
for i, item in enumerate(aLotOfItems):
database[i]=item
if i % 10000 ==0:
transaction.savepoint(True)
transaction.commit()
Run Code Online (Sandbox Code Playgroud)
我有点期望transaction.savepoint以同样的方式工作bsddb3.db.Db.sync.当Db.sync()被调用时,数据库刷新,你可以观察它.但是当设置保存点时,显然数据库和tmp文件都不会增长或者大小发生变化transaction.commit().
我真的很困惑:
设置保存点时实际发生了什么?
它与提交/刷新数据库有什么不同?
如果"要临时存储在磁盘上的数据",保存点在哪里写入数据?
我可以依靠保存点来实现"免费记忆"吗?
保存点的原始主要用途是能够回滚事务的某些部分.
假设您想接受大量日志条目,但需要将这些条目批量处理到数据库中:
for batch in per_batch(log_entries):
sp = transaction.savepoint()
try:
process_batch(batch)
except BatchFailedException:
sp.rollback()
transaction.commit()
raise
Run Code Online (Sandbox Code Playgroud)
现在已提交事务,但最后一批已回滚.
这是使用保存点的最初原因.设置保存点具有触发ZODB缓存垃圾收集运行的副作用.
ZODB保存最近访问的对象的缓存.这包括在当前事务中实际不会更改的对象; 您只是从数据库中检索它们,使用它们的数据,然后停止直接引用它们.ZODB存储对象图; 一个对象引用其他对象,而这些对象又引用其他对象.如果这些对象从Persistent基类继承,则每个对象都是单独的ZODB记录.遍历图形时,这些对象都会加载到内存中.
GC运行会再次从内存中清除它们,前提是它们没有更改.再次遍历对象图将再次将它们加载到内存中,但在保存点期间清除它们可以节省内存.
Savepoint数据本身存储在磁盘中的目录中的TmpStorage文件中TEMP.这使用了一个tempfile.TemporaryFile()对象,出于安全原因,该对象是在未链接状态下创建的; 文件存在,但目录条目在创建时立即清除.因此,您无法在ZODB进程外部看到此文件.
完整提交将数据移动到实际的ZODB数据库中并完成事务.