由于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