南大通用GBase 8a 由于文件系统ext4损坏,导致分片表丢失的现象分析

GBase 8a数据库集群,所有数据都保存在操作系统的文件系统里,比如ext4, 当文件系统故障时,数据库会报各类存储错误,继而将分片设置为dmlstorageevent。而这类错误的修复方案是先将数据删掉,此时分片表将无法从故障分片查询到,然后从副本整个同步一份。如果副本这时也出现相同的损坏,则表分片将无法恢复,数据丢失。

报错现象:

报错包括 data file corrupted 或者borken, storage engine error等。

报错样例

当主副本都报错时

排查过程

查看gcadmin showdmlstorageevent, 确实看到了主备分片都是1的状态。在1+2的环境,67,68,69三个IP的n38分片,全部是故障状态。

检查操作系统日志

再3个节点检查/var/log/messages及其历史日志,都发现了ext4-fs的文件系统错误。且重复出现很多次。

查看数据目录,确实没有了_n38的文件和目录

其中一个节点存在目录,但查询报错

分析

GBase 8a数据库集群,在处理dmlstorageevent时,会先把故障分片表数据全部删除,这导致了部分节点看不到磁盘目录和文件。 当副本也故障时,系统无法自动修复,故障也就一直存在。而所有主副本都是故障状态,就报了 no valid node for suffix _n38

解决方案

在主副本都是存储级错误时,没有合适的方案恢复数据,只有牺牲这个分片了。具体做法:

1、清理掉这几个event, 参考 GBase 8a手工清理Event

2、然后进gncli,将所有这个分片表的残留删除。 drop table XXXX_n38. 主副本都要清理掉残余。

3、手工在主副本节点,重建表结构。 create table XXXX_n38。

这样,数据表就损失这着个分片的数据,但可以保证后续的查询正常。

郑重提醒

如果你处理的表,是当前正在加载的表,强烈建议你处理完毕后,重新建一个新表,把数据insert select 过去,然后表重命名。 因为数据库在内部是有个tableid的,但我们表已经丢失,找不到tableid了,所以手工重建的是table=0, 这在后面如果再次发生数据不一致,在同步是会出现问题。

所以对历史表,可以如上解决,对实时表,建议处理后,再整体重建一次解决。