F.20. lo

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

F.20.1. 原理

JDBC驱动的问题之一(也影响ODBC驱动),是规范假设BLOB(二进制大对象)的参数是存储在一个表内的, 并且如果该项改变了,那么相关的BLOB会从数据库中删除。

作为PostgreSQL标准,这个不会发生。大对象被视为对象; 一个表项可以通过OID引用一个大对象,不过可能多个表项引用同一个大对象OID, 所以系统不会因为你改变或删除一个表项就删除大对象。

这对PostgreSQL专有应用来说很好,但是使用JDBC或ODBC的标准代码不会删除大对象, 导致孤独的对象—对象不被任何东西引用,只是简单的占用磁盘空间。

lo模块允许通过在包含LO引用字段的表上附加一个触发器修复这个问题。 该触发器本质上只是在你删除或修改一个引用大对象的值时做lo_unlink。 当使用这个触发器时,假设只有一个数据库引用被触发器控制字段引用的任意的大对象。

该模块也支持数据类型lo,该类型实际上只是一个oid类型的域。 这对于区别持有大对象引用的数据库字段和那些其他事情的OID有帮助。 你不必使用lo类型来使用该触发器, 但是使用它会很方便的记录你的数据库中的哪个字段代表管理该触发器的大对象, 如果你不为BLOB字段使用lo,据说ODBC驱动器也会感到迷惑。

F.20.2. 怎样使用

这是一个使用的简单的例子:

CREATE TABLE image (title TEXT, raster lo);

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

对于每个将要包含大对象的唯一引用的字段,创建一个BEFORE UPDATE OR DELETE 触发器,并将字段名作为触发器唯一的参数。你也可以通过使用BEFORE UPDATE OF _column_name_ 限制触发器只在该字段更新时执行。如果你在相同的表中需要多个lo字段, 那么为每个字段创建一个单独的触发器,记得给相同表上的每个触发器以不同的名字。

F.20.3. 限制

  • 删除一个表仍然将孤立它包含的任意对象,因为触发器没有执行。你可以通过在DROP TABLE之前DELETE FROM _table_来避免这个问题。

    TRUNCATE有同样的危险。

    如果你已经有或者怀疑你有孤立的大对象,参阅vacuumlo 模块帮助你清除它们。偶尔运行vacuumlo 作为lo_manage触发器的后备是一个好主意。

  • 一些前端可能创建他们自己的表,并且不创建相关的触发器。还有,用户可能不记得(或知道) 创建触发器。

F.20.4. 作者

Peter Mount <[[email protected]](mailto:[email protected])>