前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PG中的blob cleanup

PG中的blob cleanup

作者头像
yzsDBA
发布2021-01-05 14:36:33
1.4K0
发布2021-01-05 14:36:33
举报

PG中的blob cleanup

PG提供了一个很好的BLOB接口,得到了广泛应用。然而最近我们遇到了各种客户遇到的问题,有必要对PG如何处理blob进行一次思考,尤其是BLOB清理。

PG的BLOB接口

PG中可以使用各种方式存储二进制数据,最简单的方式是定义一个“bytea”(=byte array)数据类型。也就是定义一个bytea列:

test=# CREATE TABLE t_image (id int, name text, image bytea);

CREATE TABLE

test=# \d t_image

Table "public.t_image"

Column | Type | Collation | Nullable | Default

-------+---------+-----------+----------+---------

id | integer | | |

name | text | | |

image | bytea | | |

如你所见,这是一个普通列,可以像普通列一样使用。唯一值得一提的是必须在SQL级别使用的编码。PG使用一个变量来配置此行为:

test=# SHOW bytea_output;

bytea_output

--------------

hex

(1 row)

bytea_output有两个值,hex:表示PG以16进制格式发送数据,escape:表示以8进制发送。除了每个字段最大大小限制1GB外,应用程序在这里不需要担心太多。

PG还有第二种接口处理二进制数据:BLOB接口。例子:

test=# SELECT lo_import('/etc/hosts');

lo_import

-----------

80343

(1 row)

这个例子中,“/etc/hosts”内容存储到了数据库。PG有这个数据的副本而不是到文件系统的链接。需要注意,数据库将返回新条目的OID(存储到了系统表),为了跟踪这些OID,一些开发人员执行以下操作:

test=# CREATE TABLE t_file (

id int,

name text,

object_id oid

);

CREATE TABLE

test=# INSERT INTO t_file

VALUES (1, 'some_name', lo_import('/etc/hosts'))

RETURNING *;

id | name | object_id

----+---------------+-----------

1 | some_name | 80350

(1 row)

1

INSERT 0 1

除了做下面动作,其他方面都还好:

test=# DELETE FROM t_file WHERE id = 1;

DELETE 1

问题是对象的OID被遗忘了,虽然删除了t_file里的一个记录,但是二进制数据仍然存在。PG通过pg_largeobject系统表存储二进制数据。所有的lo_functions为了处理下面事情会和该系统表交互:

test=# \x

Expanded display is on.

test=# SELECT * FROM pg_largeobject WHERE loid = 80350;

-[ RECORD 1 ]------------------------------------------

loid | 80350

pageno | 0

data | ##\012# Host Database\012#\012# localhost ...

问题是什么?原因很简单,数据库会膨胀,因此删除BLOB条目正确的方法是:

test=# \x

Expanded display is off.

test=#

test=# SELECT lo_unlink(80350);

lo_unlink

-----------

1

(1 row)

test=# SELECT * FROM pg_largeobject WHERE loid = 80350;

loid | pageno | data

------+--------+------

(0 rows)

如果忘记删除object,我们经常会遇到这样的事情:你将遭受膨胀带来的痛苦。如果使用BLOB接口,这是一个主要问题。

vacuumlo:清理死大对象

然而,一旦积累了成千上万的死blob,如何解决这个问题呢?可以通过vacuumlo工具:

test=# SELECT lo_import('/etc/hosts');

lo_import

-----------

80351

(1 row)

iMac:~ hs$ vacuumlo -h localhost -v test

Connected to database "test"

Checking object_id in public.t_file

Successfully removed 2 large objects from database "test".

可以看到,死大对象被清理了。

额外函数

PG提供了不止lo_import和lo_unlink函数:

test=# \df lo_*

List of functions

Schema | Name | Result data type | Argument data types | Type

------------+---------------+------------------+---------------------------+------

pg_catalog | lo_close | integer | integer | func

pg_catalog | lo_creat | oid | integer | func

pg_catalog | lo_create | oid | oid | func

pg_catalog | lo_export | integer | oid, text | func

pg_catalog | lo_from_bytea | oid | oid, bytea | func

pg_catalog | lo_get | bytea | oid | func

pg_catalog | lo_get | bytea | oid, bigint, integer | func

pg_catalog | lo_import | oid | text | func

pg_catalog | lo_import | oid | text, oid | func

pg_catalog | lo_lseek | integer | integer, integer, integer | func

pg_catalog | lo_lseek64 | bigint | integer, bigint, integer | func

pg_catalog | lo_open | integer | oid, integer | func

pg_catalog | lo_put | void | oid, bigint, bytea | func

pg_catalog | lo_tell | integer | integer | func

pg_catalog | lo_tell64 | bigint | integer | func

pg_catalog | lo_truncate | integer | integer, integer | func

pg_catalog | lo_truncate64 | integer | integer, bigint | func

pg_catalog | lo_unlink | integer | oid | func

(18 rows)

由于历史原因,还有2个函数没有遵循命名约定:lowrite和loread:

pg_catalog | loread | bytea | integer, integer | func

pg_catalog | lowrite | integer | integer, bytea | func

最后

PG的BLOB接口非常有用。美妙之处在于它完全是事务性的,因此二进制内容和元数据sync后不会丢失。

原文

https://www.cybertec-postgresql.com/en/blob-cleanup-in-postgresql/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 yanzongshuaiDBA 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • PG中的blob cleanup
    • PG的BLOB接口
      • vacuumlo:清理死大对象
        • 额外函数
          • 最后
            • 原文
            相关产品与服务
            数据库
            云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档