9.3 9.4 9.5 9.6 10 11 12 13 14 Current(15)
阿里云PostgreSQL 问题报告 纠错本页面

F.22. lo

F.22.1. 原理
F.22.2. 如何使用它
F.22.3. 限制
F.22.4. 作者

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

这个模块被视为trusted,也就是说,它能够由当前数据库中具有CREATE特权的非超级用户来安装。

F.22.1. 原理

JDBC 驱动的问题之一(并且这也影响 ODBC 驱动)是其说明书假定对 BLOB(二进制大对象)的引用被存储在一个表中,并且如果该项被改变相关的 BLOB 会被从数据库删除。

但对于PostgreSQL来说这并不会发生。大对象被当做自主的对象,一个表项可以通过 OID 引用一个大对象,但是可以有多个表项引用同一个大对象 OID,因此系统不会因为你改变或者删除这种项而删除大对象。

现在这对PostgreSQL-相关的应用挺好的,但是使用 JDBC 或 ODBC 的标准代码不会删除那些对象,从而导致孤立对象 — 不被任何东西引用的对象,而且会占据磁盘空间。

lo允许通过附加一个触发器到包含 LO 引用列的表来修复这种问题。该触发器本质上只是在你删除或修改一个引用大对象的值时做lo_unlink。当你使用这个触发器时,你必须假定在一个触发器控制的列中只有一个对任意大对象的数据库引用!

该模块还提供了一个数据类型lo,实际上只是oid类型上的一个 。 这对于区分保存大对象引用的数据库列和其他OID的列非常有用。您不必使用lo类型来使用触发器, 但使用它来跟踪数据库中表示您正在使用触发器管理的大对象的列可能很方便。也有传言称,如果您不对BLOB列使用 lo,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