支持的版本:当前 (17) / 16 / 15 / 14 / 13
开发版本:devel
不支持的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3

F.21. lo — 管理大对象 #

lo 模块提供了对管理大对象(也称为 LO 或 BLOB)的支持。这包括数据类型 lo 和触发器 lo_manage

此模块被认为是 受信任的,也就是说,具有当前数据库的 CREATE 权限的非超级用户也可以安装它。

F.21.1. 原理 #

JDBC 驱动程序(以及 ODBC 驱动程序)存在的一个问题是,规范假定对 BLOB(二进制大对象)的引用存储在表中,如果该条目被更改,则关联的 BLOB 将从数据库中删除。

按照 PostgreSQL 的现状,这种情况不会发生。大对象被视为其自身的对象;表条目可以通过 OID 引用大对象,但是可以有多个表条目引用同一个大对象 OID,因此系统不会因为您更改或删除一个这样的条目就删除大对象。

现在,这对于特定于 PostgreSQL 的应用程序来说很好,但是使用 JDBC 或 ODBC 的标准代码不会删除对象,从而导致孤立对象 — 未被任何内容引用的对象,并且仅占用磁盘空间。

lo 模块允许通过将触发器附加到包含 LO 引用列的表来解决此问题。触发器本质上只是在您删除或修改引用大对象的值时执行 lo_unlink。当您使用此触发器时,您假设在触发器控制的列中引用的任何大对象只有一个数据库引用!

该模块还提供了一种数据类型 lo,它实际上只是 oid 类型上的一个别名。这对于区分保存大对象引用的数据库列与其他 OID 的列很有用。您不必使用 lo 类型来使用触发器,但是使用它来跟踪数据库中哪些列表示您正在使用触发器管理的大对象可能很方便。据传,如果您不使用 lo 作为 BLOB 列,ODBC 驱动程序也会感到困惑。

F.21.2. 如何使用 #

这是一个简单的使用示例

CREATE TABLE image (title text, raster lo);

CREATE TRIGGER t_raster BEFORE UPDATE OR DELETE ON image
    FOR EACH ROW EXECUTE FUNCTION lo_manage(raster);

对于将包含对大对象的唯一引用的每个列,创建一个 BEFORE UPDATE OR DELETE 触发器,并将列名作为唯一的触发器参数。您还可以通过使用 BEFORE UPDATE OF 列名 将触发器限制为仅在更新列时执行。如果需要在同一表中包含多个 lo 列,请为每个列创建一个单独的触发器,请记住为同一表上的每个触发器提供不同的名称。

F.21.3. 限制 #

  • 删除表仍然会使它包含的所有对象成为孤立对象,因为触发器不会执行。您可以通过在 DROP TABLE 之前使用 DELETE FROM 来避免这种情况。

    TRUNCATE 也存在相同的风险。

    如果您已经有或者怀疑有孤立的大对象,请参阅 vacuumlo 模块以帮助您清理它们。最好偶尔运行 vacuumlo 作为 lo_manage 触发器的后备。

  • 某些前端可能会创建自己的表,并且不会创建关联的触发器。此外,用户可能不记得(或不知道)创建触发器。

F.21.4. 作者 #

Peter Mount

提交更正

如果您在文档中看到任何不正确的内容,与特定功能的体验不符或需要进一步澄清的内容,请使用此表单报告文档问题。