9.3 9.4 9.5 9.6 10 11 12
阿里云PostgreSQL 问题报告 纠错本页面

F.21. lo

F.21.1. 原理
F.21.2. 如何使用它
F.21.3. 限制
F.21.4. 作者

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

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 PROCEDURE lo_manage(raster);

对每一个将包含到大对象唯一引用的列,创建一个BEFORE UPDATE OR DELETE触发器,并且将该列名作为唯一的触发器参数。你也可以用BEFORE UPDATE OF column_name来限制该触发器只对该列上的更新事件执行。如果你需要在同一个表中有多个lo列,为每一个创建一个独立的触发器,记住为同一个表上的每个触发器指定一个不同的名称。

F.21.3. 限制

  • 删除一个表仍将让它包含的任何对象变成孤立的,因为触发器在这种情况下不会被执行。你可以在DROP TABLE之前放上DELETE FROM table来避免这种问题。

    TRUNCATE有同样的危害。

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

  • 有些前端可能会创建它们自己的表,并且将不会创建相关的触发器。另外,用户可能不会记得(或知道)要创建触发器。

F.21.4. 作者

Peter Mount