F.22. lo — 管理大型对象#
lo
模块提供对管理大型对象(也称为 LO 或 BLOB)的支持。这包括数据类型lo
和触发器lo_manage
。
此模块被认为是“受信任”,也就是说,它可以由具有当前数据库的CREATE
权限的非超级用户安装。
F.22.1. 基本原理#
JDBC 驱动程序(这也影响 ODBC 驱动程序)的一个问题是,该规范假设对 BLOB(二进制大型对象)的引用存储在表中,并且如果该条目发生更改,则关联的 BLOB 将从数据库中删除。
正如PostgreSQL所述,这种情况不会发生。大型对象被视为本身就是对象;表条目可以通过 OID 引用大型对象,但可以有多个表条目引用相同的大型对象 OID,因此系统不会仅仅因为您更改或删除一个此类条目就删除大型对象。
现在,这对于PostgreSQL特定的应用程序来说很好,但使用 JDBC 或 ODBC 的标准代码不会删除对象,从而导致孤立对象——不受任何引用且仅占用磁盘空间的对象。
lo
模块允许通过将触发器附加到包含 LO 引用列的表来修复此问题。触发器本质上只在您删除或修改引用大型对象的某个值时执行lo_unlink
。当您使用此触发器时,您假设在触发器控制的列中引用的任何大型对象只有一个数据库引用!
该模块还提供数据类型lo
,它实际上只是域,类型为oid
。这对于区分保存大型对象引用的数据库列和保存其他内容的 OID 的数据库列非常有用。您不必使用lo
类型来使用触发器,但使用它来跟踪数据库中哪些列表示您使用触发器管理的大型对象可能很方便。还有传言称,如果您不将lo
用于 BLOB 列,则 ODBC 驱动程序会感到困惑。
F.22.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.22.3. 限制#
删除表仍会使表中包含的任何对象成为孤立对象,因为不会执行触发器。您可以通过在
DROP TABLE
前加上DELETE FROM
来避免这种情况。table
TRUNCATE
具有相同的危害。如果您已经拥有或怀疑拥有孤立的大型对象,请参阅 vacuumlo 模块以帮助您清理它们。最好偶尔运行 vacuumlo 作为
lo_manage
触发器的后备。某些前端可能会创建自己的表,并且不会创建关联的触发器。此外,用户可能不记得(或不知道)创建触发器。
F.22.4. 作者#
Peter Mount<[[email protected]](/cdn-cgi/l/email-protection#7101140514033103140514015f1e03165f041a)>