业务描述
分区表过大,历史数据没删除,和研发沟商量好保留策略后对相关分区数据进行备份、清理。主库上业务较繁忙,从库上暂无业务,故打算先在从库上删,待主备切换之后再删老主库上的数据。(删除前已完成mysqldump备份)
误操作情况说明
由于数张表要求的保留期限不一样,有的要求保留19年10月1日之后的数据,有的需要保留19年1月1日之后的数据。 为了安全, 也为了删除效率,在执行 alter 语句删除之前,先通过脚本将每个分区的 .ibd 文件做了一个硬链接。 在脚本中,误将一张保留需求是 19年1月1日的表 的时间指定成了 19年10月1日。因此,做硬链接的时候多链了9个月的分区。悲催的是删除的时候脚本指定的时间也范了同样的错误,因此多删了9个月的分区(当然这些分区也是一年多前的分区了,数据早已不会变化)。
在误操作之后,突然意识到好像搞错了, 然后就想办法拯救。 因为从库上暂时没放业务,因此我又充分的时间进行修复。 然后又因为有备份,主库的数据也没删除,还有文件的硬链接在,所以心里也不是很慌。 此表9个月的数据大约30G, 删除之前刚做过逻辑备份,目测用备份恢复也用不了多久,但我想希望尝试一下通过硬链接还原,所以就有了接下来的操作。
恢复方案
恢复方案借鉴mysql 传输表空间,与之不同的是,我这里不需要去主库上生成 xxx.cfg 文件。 恢复思路如下:
1、通过 REORGANIZE 分裂第一个分区(p20191001),把误删的分区结构补回来。
2、通过 DISCARD语句 ,将新生成的相关分区的.ibd 文件丢弃。
3、用硬链接回链到原数据文件目录。
4、通过 IMPORT PARTITION 语句导入相关分区 。
操作:
原表结构:
test>show create table emp_test \G
*************************** 1. row ***************************
Table: emp_2
Create Table: CREATE TABLEemp_test
(
id
bigint(20) unsigned NOT NULL AUTO_INCREMENT,
x
varchar(500) COLLATE utf8mb4_bin NOT NULL,
y
varchar(500) COLLATE utf8mb4_bin NOT NULL,
PRIMARY KEY (id
)
) ENGINE=InnoDB AUTO_INCREMENT=3000 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
/*!50500 PARTITION BY RANGE COLUMNS(id)
(PARTITION p1 VALUES LESS THAN (1000) ENGINE = InnoDB,
PARTITION p2 VALUES LESS THAN (2000) ENGINE = InnoDB,
PARTITION p3 VALUES LESS THAN (3000) ENGINE = InnoDB) */
1 row in set (0.00 sec)
硬链接操作:
ln /data/mysql/mydata3306/test/emp_test#P#p1.ibd /data/bak/emp_test#P#p1.ibd_hdlk
ln /data/mysql/mydata3306/test/emp_test#P#p2.ibd /data/bak/emp_test#P#p2.ibd_hdlk
模拟误删操作:
alter table emp_test drop partition p1 ;
alter table emp_test drop partition p2 ;
重新添加P1,P2分区:
alter table emp_test REORGANIZE PARTITION p3 INTO(PARTITION p2 VALUES less than (2000),PARTITION p3 VALUES less than (3000) ) ;
alter table emp_test REORGANIZE PARTITION p2 INTO(PARTITION p1 VALUES less than (1000),PARTITION p2 VALUES less than (2000) ) ;
丢弃新生成的数据文件:
ALTER TABLE emp_test DISCARD PARTITION p1, p2 TABLESPACE;
原文件回链:
ln /data/bak/emp_test#P#p1.ibd_hdlk /data/mysql/mydata3306/test/emp_test#P#p1.ibd
ln /data/bak/emp_test#P#p2.ibd_hdlk /data/mysql/mydata3306/test/emp_test#P#p2.ibd
导入新生成的数据文件:
ALTER TABLE emp_test IMPORT PARTITION p1, p2 TABLESPACE;
至此,表的结构和数据就已恢复。执行导入时可能会看到 warning 1810 xxx 之类的警告,不影响数据的正常访问,可忽略。