如何在带有 sqlite 后端的 zodb relstorage 中使用大于 1GB 的 blob?

How to use blobs > 1GB in zodb relstorage with sqlite backend?

我正在尝试通过 relstorage 在 sqlite 后端中保存大于 1GB 的 blob。以下最小工作示例

最小工作示例:

import os
import shutil
from ZODB import blob, config

connectionString = """
%import relstorage
<zodb main>
<relstorage>
    blob-dir blob
    keep-history false
    cache-local-mb 0
    <sqlite3>
        data-dir .
    </sqlite3>
</relstorage>
</zodb>
"""

# cleaning up
for x in os.listdir():
    if "sqlite" in x:
        os.remove(x)

shutil.rmtree("blob", True)

# creating database
db = config.databaseFromString(connectionString)

with db.transaction() as conn:
    conn.root.blob = blob.Blob()
    with conn.root.blob.open("w") as f:
        f.write(b"[=10=]" * 1024 ** 3)

在提交新创建的对象(在 db.transaction with 块的 __exit__ 方法处)期间发生错误,并出现以下最终异常:

sqlite3.InterfaceError: Error binding parameter 2 - probably unsupported type.

保存大小为 1024 ** 2 的 blob 不会引发异常。

如何在不使用共享 blob 目录的情况下使用 relstorage 在 sqlite 后端保存 blob?

根据我的研究,您不能在此设置中存储任意大小的 blob。您正在达到 sqlite blob 大小限制 (https://www.sqlite.org/limits.html)。

你在这个阶段唯一的选择似乎是:

  1. 不要将 blob 存储在 sqlite 中,例如通过使用共享的 blob 目录。
  2. 增加 blob 限制,使用自定义构建的 sqlite(如上文所述link)。
  3. 减小存储的大小 - 例如通过压缩您的 blob,或将您的数据分成更小的 blob。
  4. 移动到不同的存储后端。

就我个人而言,如果我使用的是 sqlite,我会倾向于使用共享的 blob 目录,但是您已经取消了该选项,所以我认为您的选择是有限的。

I am trying to save a blob > 1GB via relstorage in a sqlite backend.

一个相关的答案是this一个。

我的建议是处理不同的大 blob(例如 2020 年大于 8 到 32MBytes)和小 blob。

大内容将保存为文件,您的 sqlite 数据库会知道(并存储)文件路径(例如某些生成的文件路径,例如 Linux 上的 /var/tmp/bigblob1234。请参阅 hier(7) and inode(7)...)。

小内容将保存为 SQLITE blob。

当然你的 database schema and the Python code using it should be improved. Be aware of database normalization.