表回收站

Hologres支持表回收站功能,能够将执行DROP TABLE操作所删除的表自动保存至回收站。您可以根据业务需求对已删除的表进行恢复,以避免因误操作造成的数据丢失。

使用限制

Hologres V3.1及以上版本的实例支持表回收站功能。

回收机制

使用DROP TABLE [CASCADE]DROP DYNAMIC TABLE [CASCADE]命令删除的内部表、分区表(分区父表和子表)或Dynamic Table表,会自动进入回收站。

回收站中的表会单独存放在名为hg_recyclebinSchema中,表名与被删除前相同,数据、表属性、表索引等都会被保留在回收站中。

说明
  • 如果执行的是TRUNCATEINSERT OVERWRITE命令,表不进入回收站。

  • 不支持回收外部表、视图(VIEW)及物化视图(MATERIALIZED VIEW)。

  • 如果表设置了TTL,TTL在回收站中仍然生效。系统会根据设置的TTL,定期清理表数据。

开启/关闭回收站

--开启对应db的回收站功能
ALTER DATABASE <db_name> SET hg_enable_recyclebin = ON; 

--关闭对应db的回收站功能
ALTER DATABASE <db_name> SET hg_enable_recyclebin = OFF; 
说明
  • V3.1或以上版本的新建实例和存量实例,默认开启表回收站功能,被删除的表会自动进入表回收站。

  • 关闭回收站后,回收站中已有的表可以被恢复和清理。但关闭之后,被删除的表将不会进入回收站。

  • 仅当前实例的Superuser可执行该SQL命令,一个DB只需执行一次。

恢复表

您可使用如下命令恢复已删除的表,如果有同名表,可通过指定table_id进行还原。

RECOVER TABLE <table_name> [WITH (table_id = xxxx)]; 

注意事项如下:

  • 恢复表时

    会恢复表的数据和表属性、表索引(如PK、Clustering Key、Segment Key)等,如果表设置了TTL,则TTL在回收站中仍然生效,系统会根据设置的TTL,定期清理表数据。

  • 恢复表之前

    • 如果Schema中存在同名表,需要先删除或重命名同名表,否则会导致RECOVER执行失败。但如果同名表有设置PK、Clustering key,需要将该同名表移动到其他Schema,才能执行RECOVER,详情请参见下方的使用示例

    • 如果表所在的Schema已经被删除,恢复表操作将会失败。

  • 对于分区表

    • 分区子表恢复后将变为一张普通表,您需要将其手动ATTACH到父表上。

    • 如果恢复的是分区父表,恢复时会将父表和子表一起恢复成原始的分区表,子表无需手动ATTACH。

    • 如果分区父表开启了动态分区,恢复后将不会自动配置动态分区,需要手动开启,详情请参见动态分区管理

  • 对于Dynamic Table动态表

    • Dynamic Table恢复后是普通表,只能查数据,不具备自动刷新的能力,如有需要请重新创建Dynamic Table,详情请参见ALTER DYNAMIC TABLE

    • 恢复Dynamic Table的基表时,Dynamic Table不会被恢复。

  • 对于级联场景

    执行DROP TABLE xxx CASCADE命令删除表时,其依赖对象VIEW、MATERIALIZED VIEW均会被删除,在RECOVER表时,只能恢复目标表,无法恢复VIEW、MATERIALIZED VIEWDynamic Table,也不能恢复级联的Dynamic Table。

    例如:Dynamic Table依赖view1,view1依赖table1,DROP TABLE table1 CASCADE命令会将Dynamic Tableview1一起删除。执行RECOVER命令后,Dynamic Tableview1都不能恢复,需要重新手动创建。

  • 恢复表的权限

    执行RECOVER需要具备一定的权限。详情请参见权限说明

管理回收站

回收站支持的操作

回收站中的表支持如下操作:

  • RECOVER(恢复表)、PURGE(清理表)。

  • 通过hologres.hg_recyclebin查看回收站表详情。

查看回收站表详情

您可通过如下语句查看回收站中的表详情:

说明

Owner在回收站中仅能查看自己作为Owner的表,看不到其他用户的表。Superuser可以查看所有回收站中的所有表。

SELECT * FROM hologres.hg_recyclebin;

返回信息的参数说明如下:

参数名

描述

table_id

表在回收站中的ID,唯一值,用来识别表.

schema_name

表被删除前所在的Schema。

table_name

被删除的表名。

table_owner

表被删除前的Owner。

dropby

表的删除者。

drop_time

表被删除的时间。

查看回收站中表存储

您可通过如下语法查看回收站中表的存储量。其中:table_id不是必填项,在当Schema名和表名完全重复时,可以通过table_id指定特定的表。

--查看回收站中表存储的大小
SELECT hologres.hg_recyclebin_relation_size('<schema_name.table_name>'[,<table_id>]);

--通过如下语法可以带上存储单位
SELECT PG_SIZE_PRETTY(hologres.hg_recyclebin_relation_size('<schema_name.table_name>'[,<table_id>]));

使用示例如下:

--假设被删除的表名为tbl1,从属于public Schema
SELECT hologres.hg_recyclebin_relation_size('public.tbl1');

--如果回收站中有多个表的Schema名和表名完全一样,则额外需要使用table_id来指定查询特定表的存储量。例如:
SELECT hologres.hg_recyclebin_relation_size('public.tbl1', 42);

设置回收站的保留时间

被删除的表进入回收站后,默认保留1天,超过1天系统将自动清理该表,且无法恢复。您可设置开启或关闭回收站,也可根据业务需求使用如下语法修改回收站的保留时长。

ALTER DATABASE <db_name> SET hg_recyclebin_retention_days = 5; --修改表的保留时长为5天
说明
  • 回收站中的表仍然会参与存储计费,收取存储费用。

  • 保留时长的单位是天,最少1天,最多10天。

  • Superuser有权执行该语句,且在DB级别生效。

清理回收站中的表

您可通过PURGE命令手动清理回收站中的表。命令如下:

--清理单个表
purge TABLE {table_name};

--清空回收站中的所有表,需要使用superuser执行。
CALL hologres.hg_purge_all_tables();
说明
  • 命令执行成功后,表将会被立即删除,回收站中无法查到,也无法恢复。

  • 只能清理Table,不能清理级联的Dynamic Table。

  • 清理表权限:执行PURGE需要具备一定的权限,详情请参见权限说明

删除后的表不进入回收站

默认通过DROP TABLEDROP Dynamic Table [CASCADE]命令删除的表会进入到回收站,您可通过如下命令设置删除后的表不进入回收站。

DROP TABLE <table_name> [CASCADE] FORCE;

权限说明

回收站的查询权限

  • Owner仅可查询自己删除的表,无法查看其他用户删除的表。

  • Superuser可以查询回收站中的所有表。

删除/恢复/清理回收站中的表的权限

  • 删除表

    Superuser、Developer/Admin用户组(SPM/SLPM)及表Owner(专家权限模型)有权执行DROP命令删除表,使其进入回收站。

  • 清理表

    Superuser、Developer/Admin用户组(SPM/SLPM)及表Owner(专家权限模型)有权执行PURGE命令,清理回收站中的表。

  • 恢复表

    Superuser、Developer/Admin用户组(SPM/SLPM)、表Owner(专家权限模型)及表的删除者有权执行RECOVER命令,将表恢复至原始状态。

说明
  • SPM/SLPM权限模型下,只有表进入回收站之前的Developer/Admin用户组才有权限操作回收站中的表。如果表进入回收站后,新增了从属于Developer/Admin用户组的用户,则该用户无权操作回收站中的表。

  • 当从SPM/SLPM切换到专家模式时,仅Superuser可以还原和清理回收站中的存量表。

特殊示例:

如果user1schema1Owner,user2schema1.table2Owner,那么user1可以删除schema1以及schema1.table2,但是无法访问schema1.table2,因为user2没有给user1授权。

--1、user1创建schema1,并将建表权限授予user2
CREATE SCHEMA schema1;
GRANT CREATE ON SCHEMA schema1 TO "BASIC$user2";

--2、user2创建schema1.table2,成为表owner
CREATE TABLE schema1.table2(id INT);

--user1可以删除schema1以及下面的所有对象,包括table2,但无法查看table2
SELECT * FROM schema1.table2; 
# ERROR:  permission denied for table table2

DROP SCHEMA schema1 CASCADE; 
# DROP CASCADES TO TABLE schema1.table2
# DROP SCHEMA

如果要恢复table2,有如下两种方法:

  • user1是表的删除者,可以恢复schema1下的表。

  • user2是表Owner,可以恢复表。

使用示例

删除表进入回收站并恢复

示例1:删除普通表并恢复

  1. 准备一张普通表,并执行删除操作。

    CREATE TABLE tbl1 (
      id INT NOT NULL)
    WITH (
        orientation = 'column',
        distribution_key = 'id',
        clustering_key = 'id',
        event_time_column = 'id');
    INSERT INTO tbl1 SELECT i  FROM GENERATE_SERIES(1, 1000000) i;
    DROP TABLE tbl1;
  2. 查看回收站,确认表已经进入回收站。

    SELECT * FROM hologres.hg_recyclebin;

    返回结果如下:

    table_id | schema_name | table_name |   table_owner   |    dropby   |   drop_time        
    ---------+-------------+------------+-----------------+-------------+-----------------------
           14| public      | tbl1       | xx_developer  | 1365xxxxxxxx| 2025-04-17 19:23:10+08
    (1 row)

    查看表的存储:

    SELECT (hologres.hg_recyclebin_relation_size('tbl1')/1024)::text||'KB' AS hg_recyclebin_relation_size;

    表存储结果如下:

    hg_recyclebin_relation_size 
    -----------------------------
                          1336KB
    (1 row)
  3. 恢复表。

    --恢复普通表tbl1的所有数据和属性(包括pk、clustering key等)
    RECOVER TABLE tbl1;  

示例2:删除分区表并恢复

  1. 准备一张分区表,对应的父表和子表如下:

    CREATE TABLE tbl2_parent(id INT) PARTITION BY list (id);
    CREATE TABLE tbl2_child_1 PARTITION OF tbl2_parent FOR VALUES IN (1);
    CREATE TABLE tbl2_child_2 PARTITION OF tbl2_parent FOR VALUES IN (2);
  2. 删除其中一张子表并恢复,恢复后的子表是一张普通表,需要手动Attach到原来的分区父表上。

    --删除一张分区子表
    DROP TABLE tbl2_child_1;
    
    --分区子表进入回收站
    SELECT * FROM hologres.hg_recyclebin;

    返回结果如下:

    table_id | schema_name |  table_name  |   table_owner    |   dropby  |       drop_time        
    ----------+-------------+--------------+------------------+-----------+------------------------
           16 | public      | tbl2_child_1 | xx_developer   | 1365xxxxx | 2025-04-17 19:33:30+08
    (1 row)

    恢复该分区子表,并查看该表的结构为一张普通表,不再是一张分区子表。

    RECOVER TABLE tbl2_child_1;  
    SELECT hg_dump_script('tbl2_child_1');

    返回结果如下:

     hg_dump_script                        
    --------------------------------------------------------------
     BEGIN;                                                      +
                                                                 +
     /*                                                          +
     DROP TABLE public.tbl2_child_1;                             +
     */                                                          +                   
     CREATE TABLE public.tbl2_child_1 (                          +
         id INTEGER                                              +
     ) WITH (                                                    +
     orientation = 'column',                                     +
     storage_format = 'orc',                                     +
     table_group = 'xxxx_tg_default',                            +
     table_storage_mode = 'any',                                 +
     time_to_live_in_seconds = '3153600000'                      +
     );                                                          +
                                                                 +
                                                                 +
                                                                 +
     COMMENT ON TABLE public.tbl2_child_1 IS NULL;               +
     ALTER TABLE public.tbl2_child_1 OWNER TO "xx_developer";    +
                                                                 +
                                                                 +
     END;                                                        +
     
    (1 row)
  3. 删除分区父表,恢复后,仍然是分区表。

    --删除分区父表
    DROP TABLE tbl2_parent CASCADE;
    
    --查看回收站,父表以及子表都进入回收站
    SELECT * FROM hologres.hg_recyclebin;                   

    返回结果如下:

    table_id | schema_name |  table_name  |   table_owner |      dropby   |       drop_time        
    ---------+-------------+--------------+---------------+---------------+------------------------
          17 | public      | tbl2_child_2 | xx_developer | 1365xxxxxxxx | 2025-04-17 19:41:04+08
          15 | public      | tbl2_parent  | xx_developer | 1365xxxxxxxx | 2025-04-17 19:41:04+08

    恢复分区父表。

    RECOVER TABLE tbl2_parent; 

    PSQL客户端中执行如下语句查看分区父表DDL。

    \d+ tbl2_parent;

    返回结果如下,其子表也一并被恢复。

                              Partitioned table "public.tbl2_parent"
     Column |  Type   | Collation | Nullable | Default | Storage | Stats target | Description
    --------+---------+-----------+----------+---------+---------+--------------+-------------
     id     | integer |           |          |         | plain   |              |
    Partition key: LIST (id)
    Partitions: tbl2_child_2 FOR VALUES IN (2)

示例4:恢复重名表

  • 如果表删除后,在DB中创建了一个重名表,此时恢复已删除的表会报错,需要重命名已有表。

    1. 创建表tbl6,并执行删除。

      CREATE TABLE tbl6(id INT);
      --删除表,并进入回收站
      DROP TABLE tbl6;
    2. 重新创建一个重名表tbl6,并恢复已删除的表tbl6。

      CREATE TABLE tbl6(id INT);
      RECOVER TABLE tbl6;   

      返回结果如下,恢复失败,因为存在重名表,需要删除或RENAME重名表。

      ERROR:  Table public.tbl6 already exists
    3. 将已有表tbl6重命名为tbl6_rename后,再次恢复已删除的表tbl6,即可执行成功。

      ALTER TABLE tbl6 rename to tbl6_rename;
      RECOVER TABLE tbl6; 
  • 如果已有的重名表,设置了跟删除的表相同的PK、Clustering key,无法重名表来恢复删除的表。需要将已有的重名表移动Schema或者删除才能恢复。

    1. 创建表tbl1,并执行删除。

      --创建一张表并设置pkclustering key
      CREATE TABLE tbl1 (
          col1 INT,
          col2 INT,
          col3 INT,
          PRIMARY KEY (col1, col2)
      )
      WITH (
          clustering_key = 'col1'
      );
      --删除这张表
      DROP TABLE  tbl1;
      
      --重新创建一张重名表,并设置pkclustering key
      CREATE TABLE tbl1 (
          col1 INT,
          col2 INT,
          col3 INT,
          PRIMARY KEY (col1, col2)
      )
      WITH (
          clustering_key = 'col1'
      );
      
      --查看回收站
      SELECT * FROM  hologres.hg_recyclebin;

      返回结果如下。

      table_id | schema_name | table_name |   table_owner    |      dropby      |       drop_time        
      ----------+-------------+------------+------------------+------------------+------------------------
             493497 | public      | tbl1         | 13659371xxx| 13659371xxx | 2025-04-17 20:11:08+08
    2. 在回收站直接恢复tbl1表将报错。

      --在回收站恢复删除的表,报错,无法恢复
      RECOVER  TABLE tbl1;

      报错信息如下。

      ERROR: Table public.tbl1 already exists
    3. 重命名tbl1表再恢复将报错。

      --重命名已有表
      ALTER TABLE tbl1 RENAME TO tbl2;
      
      --恢复仍然报错,因为已有表存在pkclustering key
      RECOVER  TABLE tbl1;

      报错信息如下。

      ERROR: relation "tbl1_pkey" already EXISTS IN SCHEMA "public" 
    4. tbl1表移动到其他Schema下,再进行恢复,才可恢复成功。

      CREATE SCHEMA test;
      ALTER TABLE tbl2 SET SCHEMA test;
      
      --可以成功recover
      RECOVER  TABLE tbl1;

删除表不进入回收站

--删除普通表不放入回收站
CREATE TABLE tbl1(id INT);
DROP TABLE tbl1 FORCE;   

清理回收站中的表

CREATE TABLE tbl1(id INT);
DROP TABLE tbl1;
--强制删除回收站中的表
PURGE TABLE tbl1;