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