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/
建议提前备份本地文件
删了重建
如果是测试环境,数据不重要,尽快恢复优先,建议删库重建。