回收站
在删除一个表时,数据库不会立即删除与该表关联的物理文件和回收占用空间。数据库会重命名表,并将其和任何关联对象放置到回收站中,如果表被错误删除,则可以在以后进行恢复。
回收站实际上是一个数据字典表,包含有关丢弃对象的信息。删除的表和任何关联对象(如索引、约束、类型等),它们的物理文件会保留一段时间,并且仍占用空间。
它们会继续被计入用户空间配额,直到指定从回收站中清除,或者由于表空间需要被删除时,数据库必须清空回收站。
每个用户都可以被认为有自己的回收站,因为除非用户具有 SUPERUSER
权限,否则用户在回收站中唯一有权访问的对象是用户拥有的对象。用户可以使用以下语句在回收站中查看其模式中的对象:
SELECT * FROM pg_catalog.pg_recyclebin
WHERE namespace = to_regnamespace(CURRENT_SCHEMA)::oid;
DDL 命令删除的对象将会被移动到回收站。在移动到回收站的已删除对象中包括以下类型的对象:
- 表
- 回滚段
- 索引
- 约束
- 类型
- 函数
当您删除表空间时,表空间中的对象不会放置在回收站中,数据库会清除回收站中位于表空间中的任何对象。同样:
- 删除用户时,属于该用户的任何对象都不会放置在回收站中,并且回收站中的任何对象都会清除。
- 删除模式时,属于该模式的任何对象都不会放置在回收站中,并且回收站中的任何对象都会清除。
当删除的表移动到回收站时,该表及其关联的对象将被指定为系统生成的名称。这是必要的,以避免如果多个表具有相同的名称,可能会出现名称冲突。在以下情况下可能发生这种情况:
- 用户删除表,用相同的名称重新创建表,然后再次删除表。
- 两个用户有同名的表,两个用户都删除他们的表。
删除对象重命名约定如下:
pg_dropped_[object_type]_[object_id]
其中:
object_type
是对象类型名称,例如:table, index, constraint, type, function。object_id
是该对象的唯一标识符,这使得回收站名称在当前数据库中唯一。
您可以查询系统表pg_recyclebin
以识别数据库分配给已删除对象的名称,如以下示例所示:
SELECT objname, oldname FROM pg_catalog.pg_recyclebin
WHERE namespace = to_regnamespace('hr')::oid;
objname | oldname
-----------------------+-----------
pg_dropped_table_18762 | employees
您还可以使用GUI管理工具(如 DBeaver、pgAdmin 4)查看回收站的内容,在指定数据库下展开系统模式pg_recyclebin
以查看所有已删除的对象。
您可以查询回收站中的对象,就像查询其他对象一样。但是,您必须用它在回收站中的标识指定对象的名称。例如:
SELECT * FROM pg_recyclebin.pg_dropped_table_18762;
如果您决定永远不会从回收站恢复一个删除对象,则可以使用VACUUM
语句从回收站中彻底删除指定对象及其关联对象,并释放其存储空间。您需要与删除对象时相同的权限。
使用VACUUM
语句清除表时,可以使用回收站中已知表的名称或表的原始名称。回收站名称可以从系统表pg_recyclebin
中获取,如“查看和查询回收站中的对象”所示。以下假设示例清除表hr.employees
,该表在放入回收站时被重命名为pg_recyclebin.pg_dropped_table_18762
:
VACUUM pg_recyclebin.pg_dropped_table_18762;
您可以使用以下语句获得相同的结果:
VACUUM hr.employees;
如果您具有 SUPERUSER
权限或您是当前数据库所有者,则可以使用以下语句清除整个回收站,并释放对象占用的空间:
VACUUM;
您还可以使用VACUUM
语句从回收站中清除索引或回滚段。
使用 CREATE
TABLE
… LIKE
语句可以恢复在回收站中的已删除对象。
您应该指定回收站中已删除表的名称。回收站名称可以从系统表pg_recyclebin
中获取,如“查看和查询回收站中的对象”所示。要使用 CREATE
TABLE
… LIKE
语句,您需要访问已删除表所需的SELECT
权限。
以下示例恢复 employees
表,并为其分配新名称:
CREATE TABLE hr.employees2 (LIKE pg_recyclebin.pg_dropped_table_18762 INCLUDING ALL);
INSERT INTO hr.employees2 SELECT * FROM pg_recyclebin.pg_dropped_table_18762;
如果您多次删除表,回收站中系统生成的对象名称非常有用。例如,假设您在回收站中有三个版本的 employees
表,并且您希望恢复第二个版本。您可以查询回收站,然后恢复到系统生成的相应对象名称,如以下示例所示。在查询中包括删除时间可以帮助您验证您正在恢复正确的表。
SELECT objname, oldname, droptime FROM pg_catalog.pg_recyclebin;
查询结果:
objname | oldname | droptime
-----------------------+-----------+--------------------
pg_dropped_table_18762 | employees | 2016-02-05 21:05:52
pg_dropped_table_18924 | employees | 2016-02-05 21:25:13
pg_dropped_table_19510 | employees | 2016-02-05 22:05:53
恢复指定的表对象:
CREATE TABLE hr.employees2 (LIKE pg_recyclebin.pg_dropped_table_18924 INCLUDING ALL);
INSERT INTO hr.employees2 SELECT * FROM pg_recyclebin.pg_dropped_table_18924;