南大通用GBase 8a集群查表报错Can't get distribution attribute of table

GBase 8a集群如果出现OS异常断电,死机时,可能会出现部分元数据没有正确保存到磁盘上情况,比如gbase.table_distribution表。如果集群为单节点,没有副本用于自动恢复时,可能造成部分表查询时报错Can't get distribution attribute of table。

报错样例

ERROR 1149 (42000): (GBA-02SC-1001) Can't get distribution attribute of table `testdb`.`t2_test`, please check your gbase.table_distribution.

报错原因

表的部分元数据信息保存现在gbase.table_distribution里,包括分布类型(hash分布还是随机分布),是否为复制表等。

如果表在磁盘上完全不存在,则会报not exists错误

gbase> select * from t2_test2;
ERROR 1146 (42S02): Table 'testdb.t2_test2' doesn't exist

如果该表存在,但如上元数据表数据因环境问题导致丢失,则会造成如下报错

gbase> select * from t2_test;
ERROR 1149 (42000): (GBA-02SC-1001) Can't get distribution attribute of table `testdb`.`t2_test`, please check your gbase.table_distribution.

另外,如果尝试重建表,会发现如下2个典型现象:

  • 删除表时,报未知的表(Unknown table)建表时
  • 报表已经存在(already exists)
gbase> drop table t2_test;
ERROR 1702 (HY000): gcluster table error: (GBA-02DD-0017) Unknown table 'testdb.t2_test'
gbase>
gbase> create table t2_test like t2;
ERROR 1050 (42S01): Table 't2_test' already exists
gbase>

解决方案

手工重建table_distribution数据

向gbase.table_distribution表里面,插入丢失的数据。比如

gbase> insert into table_distribution values('testdb.t2_test','testdb','t2_test','NO',null,null,null,'NO',2);
Query OK, 1 row affected (Elapsed: 00:00:00.00)
gbase> select * from table_distribution where index_name like '%t2_test%';
+----------------+--------+---------+-------------+-------------+------------------+--------------------+-------------+----------------------+
| index_name     | dbName | tbName  | isReplicate | hash_column | lmt_storage_size | table_storage_size | is_nocopies | data_distribution_id |
+----------------+--------+---------+-------------+-------------+------------------+--------------------+-------------+----------------------+
| testdb.t2_test | testdb | t2_test | NO          | NULL        |             NULL |               NULL | NO          |                    2 |
+----------------+--------+---------+-------------+-------------+------------------+--------------------+-------------+----------------------+
1 row in set (Elapsed: 00:00:00.00)

各个字段含义参考 GBase 8a元数据表gbase.table_distribution。其中

  • isReplicate 是否为复制表
  • hash_column 如果有hash列,则正确填写
  • data_distribution_id 这个可以从其它存在的可查询的表里得到,保持一致即可。

然后单独启动gclusterd服务,因为gnode上没有这个gbase.table_distribution表

[gbase@localhost gbase]$ gcluster_services gcluster restart
Stopping gcluster :                                        [  OK  ]
Starting gcluster :                                    [  OK  ]

就可以正常查询了

gbase> select * from t2_test;
Empty set (Elapsed: 00:00:00.03)

这个方案适合数据重要不能删除的情况。

排查哪些表可能丢失,可以参考如下方案

gbase> select table_name from information_schema.tables where table_schema='testdb' and table_name not in(select tbname from gbase.table_distribution where dbname='testdb');
+------------+
| table_name |
+------------+
| t2_test    |
+------------+
1 row in set (Elapsed: 00:00:00.00)

从其它集群还原

如果有其它环境,表完全一样,可以将该表数据复制过来,然后本地重启服务即可

scp gbase@XXXX:/opt/gbase/gcluster/userdata/gcluster/gbase/table_distribution.* /opt/gbase/gcluster/userdata/gcluster/gbase/

建议提前备份本地文件

删了重建

如果是测试环境,数据不重要,尽快恢复优先,建议删库重建。