GBase 8a本身没有回收站功能,被删除的数据是不能通过SQL命令直接恢复的。本文介绍一种非正常手段,用来【尝试】恢复最后一次删除的数据。
目录导航
警告
本操作属于非正常手段:
如果你有备份,请用备份恢复
如果你能重新录入数据,请重新录入
另外本操作如果手工操作失误,可能导致当前数据主副本不一致,或者数据状态不对,从而影响后续使用,所以只有在丢失的数据极其重要时,考虑的一个【尝试性】方案。
前提
该表做完delete后,没有其它的DML,DDL等操作。否则数据已经改动了,你恢复的最后一次,可能不再是你认为的【最后一次】。
集群
2节点集群
[root@rh6-1 ~]# gcadmin
CLUSTER STATE: ACTIVE
CLUSTER MODE: NORMAL
=================================================================
| GBASE COORDINATOR CLUSTER INFORMATION |
=================================================================
| NodeName | IpAddress |gcware |gcluster |DataState |
-----------------------------------------------------------------
| coordinator1 | 10.0.2.201 | OPEN | OPEN | 0 |
-----------------------------------------------------------------
=============================================================
| GBASE DATA CLUSTER INFORMATION |
=============================================================
|NodeName | IpAddress |gnode |syncserver |DataState |
-------------------------------------------------------------
| node1 | 10.0.2.201 | OPEN | OPEN | 0 |
-------------------------------------------------------------
| node2 | 10.0.2.202 | OPEN | OPEN | 0 |
-------------------------------------------------------------
测试表
一张单列的表
gbase> create table tt(id int);
Query OK, 0 rows affected (Elapsed: 00:00:00.28)
测试数据
插入3行数据。
gbase> select * from tt;
Empty set (Elapsed: 00:00:00.01)
gbase> insert into tt values(1),(2),(3);
Query OK, 3 rows affected (Elapsed: 00:00:00.16)
Records: 3 Duplicates: 0 Warnings: 0
gbase> select * from tt;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (Elapsed: 00:00:00.01)
删除数据
通过delete删除一行数据。
gbase> delete tt where id=1;
Query OK, 1 row affected (Elapsed: 00:00:00.23)
gbase> select * from tt;
+------+
| id |
+------+
| 2 |
| 3 |
+------+
2 rows in set (Elapsed: 00:00:00.01)
建议备份
在尝试恢复前,建议对表的当前可用数据做备份。如果手工恢复出问题了,最多就是真的丢失了被删除的数据。
create table tt_bak like tt;
insert into tt_bak select * from tt;
如果恢复失败,可以通过如下步骤恢复备份
rename table tt to tt_BAD;
rename table tt_bak to tt;
尝试恢复被删除的数据
如下操作【有可能】要在每个节点执行,这涉及到你删除的数据,到底影响了哪些分片。只有有数据被本次删除的分片,才需要恢复。如果不涉及到本次删除的分片被操作了,那么可能回退到了一个你无法确认的状态了。
获得数据节点的分片号
其中的IP是主节点,后面的segment ID就是分片号。比如针对tt表,在10.0.2.202上,分片号是1,其分片表的名字就是 tt_n1。在10.0.2.210上,分片表的名字就是tt_n2。
后面的duplicate是备份表所在IP,分片名字和主分片是一样的。
[root@rh6-1 ~]# gcadmin showdistribution
Distribution ID: 2 | State: new | Total segment num: 2
Primary Segment Node IP Segment ID Duplicate Segment node IP
========================================================================================================================
| 10.0.2.202 | 1 | 10.0.2.201 |
------------------------------------------------------------------------------------------------------------------------
| 10.0.2.201 | 2 | 10.0.2.202 |
========================================================================================================================
[root@rh6-1 ~]#
查看数据节点的每个分片信息
通过information_schema.tables表,拿到该节点的分片的SCN号和最后更新信息。 需要根据update_time,判断最后删除操作,是否涉及了这个分片。
如下的输出,tt_n1的更新时间是14:20:33,而tt_n2是14:20:11,可以看出上次的delete操作,只影响了n1分片,而没有影响n2分片。对于多个数据节点的集群,每个分片都要检查一次,找到上次delete影响的分片号。
注意,各个节点的【时钟】如果不同,且表的DML操作很频繁,则【非常容易】出现【误判】,导致恢复失败。
[gbase@rh6-1 ~]$ gncli testdb
GBase client 8.6.2.43-R28 .125499. Copyright (c) 2004-2021, GBase. All Rights Reserved.
gbase> select scn,UPDATE_TIME from information_schema.tables where table_name='tt_n1';
+---------+---------------------+
| scn | UPDATE_TIME |
+---------+---------------------+
| 5242933 | 2021-06-17 14:20:33 |
+---------+---------------------+
1 row in set (Elapsed: 00:00:00.00)
gbase> select now();
+---------------------+
| now() |
+---------------------+
| 2021-06-17 14:21:11 |
+---------------------+
1 row in set (Elapsed: 00:00:00.00)
gbase> select scn,UPDATE_TIME from information_schema.tables where table_name='tt_n2';
+---------+---------------------+
| scn | UPDATE_TIME |
+---------+---------------------+
| 5242931 | 2021-06-17 14:20:11 |
+---------+---------------------+
1 row in set (Elapsed: 00:00:00.00)
gbase>
尝试回退该分片
再次声明:该操作如果评估错误,将导致数据内容处于一个不可知的状态。
根据测试的2节点集群,n1分片需要恢复,通过如下的revert语句,尝试恢复。
可以看到,tt_n1表,被删除的id=1的数据回来了。查看tables表,可以看到scn从 5242933 减少到了5242932。
[gbase@rh6-1 ~]$ gncli -h10.0.2.202 testdb
GBase client 8.6.2.43-R28 .125499. Copyright (c) 2004-2021, GBase. All Rights Reserved.
gbase> select * from testdb.tt_n1;
+------+
| id |
+------+
| 2 |
| 3 |
+------+
2 rows in set (Elapsed: 00:00:00.00)
gbase> revert table testdb.tt_n1 scn_number 5242933;
Query OK, 0 rows affected (Elapsed: 00:00:00.04)
gbase> select * from testdb.tt_n1;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (Elapsed: 00:00:00.00)
gbase> select scn,UPDATE_TIME from information_schema.tables where table_name='tt_n1';
+---------+---------------------+
| scn | UPDATE_TIME |
+---------+---------------------+
| 5242932 | 2021-06-17 14:20:21 |
+---------+---------------------+
1 row in set (Elapsed: 00:00:00.00)
针对副本,也要做相同的操作
[gbase@rh6-1 ~]$ gncli -h10.0.2.201 testdb
GBase client 8.6.2.43-R28 .125499. Copyright (c) 2004-2021, GBase. All Rights Reserved.
gbase> select * from testdb.tt_n1;
+------+
| id |
+------+
| 2 |
| 3 |
+------+
2 rows in set (Elapsed: 00:00:00.01)
gbase> revert table testdb.tt_n1 scn_number 5242933;
Query OK, 0 rows affected (Elapsed: 00:00:00.04)
gbase> select * from testdb.tt_n1;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (Elapsed: 00:00:00.00)
gbase>
回到集群查询验证
可以看到被我们删除的id=1的数据已经恢复了。
[gbase@rh6-1 ~]$ gccli testdb
GBase client 8.6.2.43-R28 .125499. Copyright (c) 2004-2021, GBase. All Rights Reserved.
gbase> select * from testdb.tt;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (Elapsed: 00:00:00.02)
意外处理
如果前面的revert弄错了,你可以通过revert再回退到最新的版本,这个revert你可以理解成【切换】的意思。但如果多个分片,切换错了,那么数据就会处于一种未知的状态了。
[gbase@rh6-1 ~]$ gncli -h10.0.2.202 testdb
GBase client 8.6.2.43-R28 .125499. Copyright (c) 2004-2021, GBase. All Rights Reserved.
gbase> select * from testdb.tt_n1;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (Elapsed: 00:00:00.00)
gbase> select scn,UPDATE_TIME from information_schema.tables where table_name='tt_n1';
+---------+---------------------+
| scn | UPDATE_TIME |
+---------+---------------------+
| 5242932 | 2021-06-17 14:20:21 |
+---------+---------------------+
1 row in set (Elapsed: 00:00:00.00)
gbase> revert table testdb.tt_n1 scn_number 5242932;
Query OK, 0 rows affected (Elapsed: 00:00:00.03)
gbase> select scn,UPDATE_TIME from information_schema.tables where table_name='tt_n1';
+---------+---------------------+
| scn | UPDATE_TIME |
+---------+---------------------+
| 5242933 | 2021-06-17 14:20:33 |
+---------+---------------------+
1 row in set (Elapsed: 00:00:00.01)
gbase> select * from testdb.tt_n1;
+------+
| id |
+------+
| 2 |
| 3 |
+------+
2 rows in set (Elapsed: 00:00:00.00)