【发布时间】:2020-12-16 04:34:28
【问题描述】:
此问题与How to pack blobstorage with Plone and RelStorage有关
使用zodb 数据库和RelStorage 和sqlite 作为其后端,我正在尝试删除未使用的blob。目前db.pack 不会从光盘中删除 blob。下面的最小工作示例演示了这种行为:
import logging
import numpy as np
import os
import persistent
from persistent.list import PersistentList
import shutil
import time
from ZODB import config, blob
connectionString = """
%import relstorage
<zodb main>
<relstorage>
blob-dir ./blob
keep-history false
cache-local-mb 0
<sqlite3>
data-dir .
</sqlite3>
</relstorage>
</zodb>
"""
class Data(persistent.Persistent):
def __init__(self, data):
super().__init__()
self.children = PersistentList()
self.data = blob.Blob()
with self.data.open("w") as f:
np.save(f, data)
def main():
logging.basicConfig(level=logging.INFO)
# Initial cleanup
for f in os.listdir("."):
if f.endswith("sqlite3"):
os.remove(f)
if os.path.exists("blob"):
shutil.rmtree("blob", True)
# Initializing database
db = config.databaseFromString(connectionString)
with db.transaction() as conn:
root = Data(np.arange(10))
conn.root.Root = root
child = Data(np.arange(10))
root.children.append(child)
# Removing child reference from root
with db.transaction() as conn:
conn.root.Root.children.pop()
db.close()
print("blob directory:", [[os.path.join(rootDir, f) for f in files] for rootDir, _, files in os.walk("blob") if files])
db = config.databaseFromString(connectionString)
db.pack(time.time() + 1)
db.close()
print("blob directory:", [[os.path.join(rootDir, f) for f in files] for rootDir, _, files in os.walk("blob") if files])
if __name__ == "__main__":
main()
上面的例子做了以下事情:
- 删除当前目录中任何以前的数据库以及 blob 目录。
- 从头开始创建一个数据库/存储,添加两个对象(root 和 child),而 child 由 root 引用并执行事务。
- 删除从根到子的链接并执行事务。
- 关闭数据库/存储
- 打开数据库/存储并在未来执行
db.pack一秒钟。
最小工作示例的输出如下:
INFO:ZODB.blob:(23376) Blob directory '<some path>/blob/' does not exist. Created new directory.
INFO:ZODB.blob:(23376) Blob temporary directory './blob/tmp' does not exist. Created new directory.
blob directory: [['blob/.layout'], ['blob/3/.lock', 'blob/3/0.03da352c4c5d8877.blob'], ['blob/6/.lock', 'blob/6/0.03da352c4c5d8877.blob']]
INFO:relstorage.storage.pack:pack: beginning pre-pack
INFO:relstorage.storage.pack:Analyzing transactions committed Thu Aug 27 11:48:17 2020 or before (TID 277592791412927078)
INFO:relstorage.adapters.packundo:pre_pack: filling the pack_object table
INFO:relstorage.adapters.packundo:pre_pack: Filled the pack_object table
INFO:relstorage.adapters.packundo:pre_pack: analyzing references from 7 object(s) (memory delta: 256.00 KB)
INFO:relstorage.adapters.packundo:pre_pack: objects analyzed: 7/7
INFO:relstorage.adapters.packundo:pre_pack: downloading pack_object and object_ref.
INFO:relstorage.adapters.packundo:pre_pack: traversing the object graph to find reachable objects.
INFO:relstorage.adapters.packundo:pre_pack: marking objects reachable: 4
INFO:relstorage.adapters.packundo:pre_pack: finished successfully
INFO:relstorage.storage.pack:pack: pre-pack complete
INFO:relstorage.adapters.packundo:pack: will remove 3 object(s)
INFO:relstorage.adapters.packundo:pack: cleaning up
INFO:relstorage.adapters.packundo:pack: finished successfully
blob directory: [['blob/.layout'], ['blob/3/.lock', 'blob/3/0.03da352c4c5d8877.blob'], ['blob/6/.lock', 'blob/6/0.03da352c4c5d8877.blob']]
如您所见,db.pack 确实删除了 3 个对象“将删除 3 个对象”,但文件系统中的 blob 没有改变。
在 RelStorage 的单元测试中,它们似乎确实测试了是否从文件系统中删除了 blob (see here),但在上面的脚本中它不起作用。
我做错了什么?任何提示/链接/帮助表示赞赏。
【问题讨论】:
-
我的回答完全偏离主题,但是:哇,过去的爆炸! RelStorage 项目是在我工作的一家核心 Plone 生态系统公司 Jarn 的最大客户要求所有数据存储在 Oracle 中时构思的。没有如果或但是!因此,我们委托 Shane Hathaway 根据他的 PGStorage 工作创建这个项目,您会发现我contributed a fair amount of work,大约十年前。很高兴看到该项目仍在进行中!
标签: python sqlite blob zodb relstorage