# 如何快速处理 OceanBase 故障

## 如何判断定位 OceanBase 故障

当 OceanBase 故障时，应用端可能会有很多报错信息反馈过来。此时需要初步判断应用是全部失败，还是有成功有失败。理论上 OceanBase 局部节点故障，应用只会是局部数据库读写故障或者中断，在1分钟左右应用就能全部恢复。

同时需要尽快确认 OceanBase 集群的状态。

+ 首先确认集群节点状态

```sql
select a.zone,concat(a.svr_ip,':',a.svr_port) observer, cpu_total, (cpu_total-cpu_assigned) cpu_free, round(mem_total/1024/1024/1024) mem_total_gb, round((mem_total-mem_assigned)/1024/1024/1024) mem_free_gb, usec_to_time(b.last_offline_time) last_offline_time, usec_to_time(b.start_service_time) start_service_time, b.status, usec_to_time(b.stop_time) stop_time 
from __all_virtual_server_stat a join __all_server b on (a.svr_ip=b.svr_ip and a.svr_port=b.svr_port)
order by a.zone, a.svr_ip
;

```

关注：

+ 节点状态 `status` ：升级前没有 `inactive` 值，升级过程中会有。
+ 节点服务时间 `start_service_time` 的时间不是默认值（`1970-01-01 08:00:00.000000`）。如果是，则表示节点还没有恢复结束。
+ 节点停止时间 `stop_time` 的时间是默认值（`1970-01-01 08:00:00.000000`）。如果不是，则表示节点被停服（ `stop server`） 了，先启动服务（`start server`）。

+ 其次确认集群近期事件

```sql
SELECT DATE_FORMAT(gmt_create, '%b%d %H:%i:%s') gmt_create_ , module, event, name1, value1, name2, value2, rs_svr_ip
FROM __all_rootservice_event_history
WHERE 1 = 1   
   AND module IN ('server','root_service','balancer')
   AND gmt_create > SUBDATE(now(),interval  1 hour)
ORDER BY gmt_create DESC
LIMIT 50;

```

注意留意节点掉线和上线事件、合并超时事件、数据迁移事件等。

## 如何处理节点掉线或宕机故障

## 修改租户变量允许 DDL

如果有租户的架构是 `1-1-1` 并且宕机的节点就是该租户的成员，宕机后可能导致租户的 DDL 报错。

```sql
MySQL [test]> create table t2 like t1;
ERROR 4624 (HY000): machine resource is not enough to hold a new unit
```

此时需要将全局变量 `ob_create_table_strict_mode`  值设置为 OFF 。

```sql
set global ob_create_table_strict_mode = off;

```

然后重新登录业务租户，就可以做 DDL 了。

注意：这个变量关闭还是有一点风险，需要尽快修复故障节点。

## 启动 OBSERVER 进程

如果节点掉线了，但是节点的进程还在，则很可能有两个原因：

+ 节点跟其他节点的时间误差超过 200ms 。这个时候首先检查时间是否同步。
+ 节点的事务日志目录空间使用率超过参数（`clog_disk_usage_limit_percentage`，默认值是 95 ，意为 95% ）定义。

如果节点进程不在，则首先尝试拉起进程。然后再观察几分钟，看进程是否再次推出。启动进程时注意用正确的方式。

```bash
# 切换到正确用户下
cd /home/admin/oceanbase-ce && bin/observer

```

如果进程还是会退出，则查看最近的进程运行日志，搜索 ERROR 信息。

```bash
cd /home/admin/oceanbase-ce 
grep ERROR log/observer.log | vim -

```

## 如何处理节点时间不同步故障

### 判断集群节点时间同步误差

节点时间同步问题需要准确判断。需要对集群中所有节点进行相互测试，测试命令是：`clockdiff` 。

```bash
[root@obce01 ~]# clockdiff 172.20.249.49
...
host=172.20.249.49 rtt=428(314)ms/0ms delta=0ms/0ms Thu Sep 30 21:33:16 2021
[root@obce01 ~]# clockdiff 172.20.249.51
...
host=172.20.249.51 rtt=426(314)ms/0ms delta=0ms/0ms Thu Sep 30 21:33:22 2021
[root@obce01 ~]#

[root@obce02 ~]# clockdiff 172.20.249.50
.
host=172.20.249.50 rtt=750(187)ms/0ms delta=0ms/0ms Thu Sep 30 21:34:10 2021
[root@obce02 ~]# clockdiff 172.20.249.52
...
host=172.20.249.52 rtt=423(315)ms/0ms delta=-1ms/-1ms Thu Sep 30 21:34:14 2021

```

在某些客户机房环境了，命令 `clockdiff` 可能会报错（原因不明）。此时可以换用 `ping` 命令，查看返回的报文信息判断时间误差。

```bash
ping -T tsandaddr 172.20.249.49 -c 3

输出：
[root@obce01 ~]# ping -T tsandaddr 172.20.249.49 -c 3
PING 172.20.249.49 (172.20.249.49) 56(124) bytes of data.
64 bytes from 172.20.249.49: icmp_seq=1 ttl=64 time=26.3 ms
TS:     172.20.249.52   48963954 absolute
        172.20.249.49   13
        172.20.249.49   0
        172.20.249.52   13

64 bytes from 172.20.249.49: icmp_seq=2 ttl=64 time=0.333 ms
TS:     172.20.249.52   48964963 absolute
        172.20.249.49   1
        172.20.249.49   0
        172.20.249.52   0

64 bytes from 172.20.249.49: icmp_seq=3 ttl=64 time=0.480 ms
TS:     172.20.249.52   48966011 absolute
        172.20.249.49   0
        172.20.249.49   0
        172.20.249.52   0


--- 172.20.249.49 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2057ms
rtt min/avg/max/mdev = 0.333/9.038/26.302/12.207 ms

```

### 修复集群节点时间同步服务

此时，主要是检查每个节点的时间 同步服务是否正常。强烈推荐使用 `chrony` 同步服务，不要使用 `ntpd`。

+ 检查 `chrony` 节点同步服务

使用 `chrony` 时间服务是为了保证 OceanBase 集群各个节点时间尽可能保证同步，下面这些命令供参考。具体使用请查看 `chrony` 官方使用说明：[Chronyc Frequently Asked Questions](https://chrony.tuxfamily.org/faq.html)

```bash
查看时间同步活动
chronyc activity

查看时间服务器
chronyc sources

查看同步状态
chronyc sources -v

校准时间服务器：
chronyc tracking
```

+ 检查节点跟选中的时间服务器之间的时间差

这里也是使用 `clockdiff` 命令。
有些时间服务器是禁止`ping` 命令的，或者防火墙是禁止 `ping` 命令的，则无法探知时间误差。
这里面的判断可能会比较复杂。

一个快速的校正时间方法就是直接使用 `ntpdate` 命令同步本节点跟时间源之间的时间。测试环境如果时间总是不同步，可以将这个命令写到 `crontab` 里，每分钟运行一次。

```bash
ntpdate -b xxx.xxx.xxx.xxx

```
