↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3
开发快照。 PostgreSQL 20devel 尚未正式发布,内容仍可能变化。

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 类型,但用它来标识数据库中哪些列表示由该触发器管理的大对象,可能会更方便。还有传言说,如果 BLOB 列不用 lo,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 column_name,将该触发器限制为仅在更新该列时执行。如果同一张表中需要多个 lo 列,就为每一列分别创建一个触发器,并记得为同一张表上的每个触发器指定不同的名称。

F.21.3. 限制 #

  • 删除表时,其中包含的任何对象仍会变成孤立对象,因为这种情况下不会执行触发器。为避免这种情况,可以先执行 DELETE FROM table,再执行 DROP TABLE。

    TRUNCATE 也有同样的风险。

    如果你已经有,或者怀疑有,孤立的大对象,请参见 vacuumlo 模块来帮助清理它们。偶尔运行 vacuumlo,作为对 lo_manage 触发器的补充保障,是个不错的主意。

  • 某些前端可能会创建自己的表,但不会创建相应的触发器。此外,用户也可能不记得(或根本不知道)要创建这些触发器。

F.21.4. 作者 #

Peter Mount

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.