Recycle Bin

由于DDL语句无法回滚,开发或运维人员如果误操作(例如DROP TABLE)可能会导致数据丢失。阿里云支持回收站(Recycle Bin)功能,临时将删除的表转移到回收站,还可以设置保留的时间,方便您找回数据,同时提供了工具包(DBMS_RECYCLE)便于您快捷使用。

前提条件

实例版本如下:

  • RDS MySQL 8.0(内核小版本20191225及以上)

  • RDS MySQL 5.7(内核小版本20210430及以上)

Recycle Bin参数

Recycle Bin设计了如下五个参数。

参数

说明

loose_recycle_bin

是否打开回收站功能,包括session级别和global级别。您可以在控制台修改参数。默认值:OFF。

loose_recycle_bin_retention

回收站保留时间,单位:秒。默认为604800,即一周。您可以在控制台修改参数。

loose_recycle_scheduler

是否打开回收站的异步清理任务线程。您可以在控制台修改参数。默认值:OFF。

loose_recycle_scheduler_interval

回收站异步清理任务线程的轮询间隔,单位:秒。默认为30。暂不开放。

loose_recycle_scheduler_purge_table_print

是否打印异步清理现场工作的详细日志。默认值:OFF。暂不开放。

重要

为了防止磁盘空间被占满,建议合理设置保留时间,并打开后台清理任务线程。

Recycle Bin介绍

  • 回收/清理机制

    • 回收机制

      执行TRUNCATE TABLE语句时,将原始表移动到专门的recycle bin目录中,并在原位置使用相同的结构创建新表。

      说明

      仅RDS MySQL 8.0(内核小版本20200331及以上)支持。

      执行DROP TABLE/DATABASE语句时,只保留相关的表对象,并移动到专门的recycle bin目录中。其它对象的删除策略如下:

      • 如果是与表无关的对象,根据操作语句决定是否保留,不做回收。

      • 如果是表的附属对象,可能会修改表数据的,做删除处理,例如Trigger和Foreign key。 但Column statistics不做清理,随表进入回收站。

    • 清理机制

      回收站会启动一个后台线程,来异步清理超过recycle_bin_retention时间的表对象。在清理回收站表的时候,如果遇到大表,会再启动一个后台线程异步删除大表。

  • 权限

    RDS MySQL实例启动时,会初始化一个名为__recycle_bin__的数据库,作为回收站使用的专有数据库。__recycle_bin__是系统级数据库,您无法直接进行修改和删除。

    对于回收站内的表,虽然您无法直接执行drop table语句,但是可以使用call dbms_recycle.purge_table('<TABLE>');进行清理。

    说明

    账号在原表和回收站表都需要具有DROP权限。

  • 回收站表命名规则

    Recycle Bin会从不同的数据库回收到统一的__recycle_bin__数据库中,所以需要保证目标表表名唯一,所以定义了如下命名格式:

    "__" + <Storage Engine> + <SE private id>

    参数说明如下。

    参数

    说明

    Storage Engine

    存储引擎名称。

    SE private id

    存储引擎为每一个表生成的唯一值。例如在InnoDB引擎中就是table id。

  • 独立回收

    回收的设置只会影响该实例本身,不会影响到日志复制到的节点(备实例、只读实例和灾备实例)上。例如我们可以在主实例上设置回收,保留7天;在备实例上设置回收,保留14天。

    说明

    回收站保留周期不同,将导致实例的空间占用差别比较大。

注意事项

  • 如果回收站数据库和待回收的表跨了文件系统,执行drop table语句将会搬迁表空间文件,耗时较长。

  • 如果Tablespace为General,可能会存在多个表共享同一个表空间的情况,当回收其中一张表的时候,不会搬迁相关的表空间文件。

管理Recycle Bin

AliSQL在Recycle Bin中提供三种管理功能。详细说明如下:

  • 查看回收站中临时保存的表

    DBMS_RECYCLE中提供展示回收站中所有临时保存的表的接口。命令如下:

    call dbms_recycle.show_tables();

    示例:

    mysql> call dbms_recycle.show_tables();
    +-----------------+---------------+---------------+--------------+---------------------+---------------------+
    | SCHEMA          | TABLE         | ORIGIN_SCHEMA | ORIGIN_TABLE | RECYCLED_TIME       | PURGE_TIME          |
    +-----------------+---------------+---------------+--------------+---------------------+---------------------+
    | __recycle_bin__ | __innodb_1063 | product_db    | t1           | 2019-08-08 11:01:46 | 2019-08-15 11:01:46 |
    | __recycle_bin__ | __innodb_1064 | product_db    | t2           | 2019-08-08 11:01:46 | 2019-08-15 11:01:46 |
    | __recycle_bin__ | __innodb_1065 | product_db    | parent       | 2019-08-08 11:01:46 | 2019-08-15 11:01:46 |
    | __recycle_bin__ | __innodb_1066 | product_db    | child        | 2019-08-08 11:01:46 | 2019-08-15 11:01:46 |
    +-----------------+---------------+---------------+--------------+---------------------+---------------------+
    4 rows in set (0.00 sec)

    参数

    说明

    SCHEMA

    回收站的数据库名。

    TABLE

    进入回收站后的表名。

    ORIGIN_SCHEMA

    原数据库名。

    ORIGIN_TABLE

    原表名。

    RECYCLED_TIME

    回收时间。

    PURGE_TIME

    预计从回收站删除的时间。

  • 手动清理回收站中的表

    DBMS_RECYCLE中提供手动清理回收站中的表的接口命令如下:

    call dbms_recycle.purge_table('<TABLE>');
    说明
    • TABLE为进入回收站后的表名。

    • 账号在原表和回收站表都需要具有DROP权限。

    示例:

    call dbms_recycle.purge_table('__innodb_1063');
  • 恢复回收站内的表数据

    • DBMS_RECYCLE中提供恢复回收站内的表的接口。

      命令示例如下:

      call dbms_recycle.restore_table('<RECYCLE_TABLE>','<DEST_DB>','<DEST_TABLE>');

      参数说明如下。

      参数

      说明

      RECYCLE_TABLE

      需要恢复的回收站内的表名。

      说明

      如果仅传入此参数,会恢复到原始表。

      DEST_DB

      目标数据库名。

      DEST_TABLE

      目标表名。

      说明

      由于restore_table命令需要SUPER权限,因此暂不支持手动执行。

      示例:

      mysql> call dbms_recycle.restore_table('__innodb_1063','testDB','testTable');
    • 使用INSERT ... SELECT恢复回收站内的表数据。

      首先查询回收站中所有临时保存的表,在SQL返回结果中查询要恢复的表在__recycle_bin__库中对应的表名。创建有相同表结构的目标表,通过INSERT ... SELECT将数据导入到目标表中。示例如下:

      mysql> call dbms_recycle.show_tables();
      +-----------------+---------------+---------------+--------------+---------------------+---------------------+
      | SCHEMA          | TABLE         | ORIGIN_SCHEMA | ORIGIN_TABLE | RECYCLED_TIME       | PURGE_TIME          |
      +-----------------+---------------+---------------+--------------+---------------------+---------------------+
      | __recycle_bin__ | __innodb_1132 | sbtest        | sbtest1      | 2024-07-31 15:08:56 | 2024-08-07 15:08:56 |
      +-----------------+---------------+---------------+--------------+---------------------+---------------------+
      1 row in set (0.00 sec)
      
      mysql> CREATE TABLE `db1`.`t1` (
          ->   `id` int NOT NULL AUTO_INCREMENT,
          ->   `k` int NOT NULL DEFAULT '0',
          ->   `c` char(120) NOT NULL DEFAULT '',
          ->   `pad` char(60) NOT NULL DEFAULT '',
          ->   PRIMARY KEY (`id`),
          ->   KEY `k_1` (`k`)
          -> ) ENGINE=InnoDB AUTO_INCREMENT=400001 DEFAULT CHARSET=utf8mb3;
      Query OK, 0 rows affected, 1 warning (0.01 sec)
      
      mysql> insert into `db1`.`t1` select * from `__recycle_bin__`.`__innodb_1132`;
      Query OK, 400000 rows affected (2.76 sec)
      Records: 400000  Duplicates: 0  Warnings: 0