隔离节点
当节点发生异常或者需要运维变更时,可以隔离节点。隔离后,新的读写请求不会路由到该节点上,从而可以隔离故障或者无损的执行运维变更动作。
-
故障隔离场景:节点发生异常时,需要将异常节点与业务流量隔离开来。例如,某机房内有交换机异常,此时某些节点出现丢包、重传,甚至无主选举。为了快速恢复,可以直接隔离这些异常节点。节点恢复后执行 Start 操作恢复节点流量。
-
运维变更场景:节点需要运维变更时,需要保证对业务流量的透明无感。例如,某节点服务器需要重启时,为了保证重启过程中不影响业务流量,可以执行节点隔离动作,从而将待重启服务器上的业务流量切到其他节点。重启动作完成后执行 Start 操作恢复节点流量。
隔离节点,只是将业务流量从该节点切走,并没有改变 Paxos 投票成员的数量。不同的隔离命令有不同的安全级别保证,需要根据执行的具体的隔离命令仔细斟酌后续能够安全执行的动作。隔离命令适用于短时间隔离的场景,需要持续保持关注,提前做好二次故障的应急预案。如果短时间内恢复不了,可以采用替换节点的方式彻底去除隐患,替换节点的详细操作请参见 替换节点。
隔离节点有以下三种命令,不同的隔离命令有不同的安全级别保证:
-
通过
STOP SERVER
命令隔离节点 -
通过
FORCE STOP SERVER
命令隔离节点 -
通过
ISOLATE SERVER
命令隔离节点
使用上述命令成功隔离节点后,被隔离节点的 STATUS
字段仍为 ACTIVE
不变,但 STOP_TIME
字段的值由 NULL
变为隔离操作的时间点,表示该节点处于 Stopped
状态。
STOP SERVER
命令格式如下,一次支持 Stop 多台 server。
obclient [(none)]> ALTER SYSTEM STOP SERVER 'svr_ip1:svr_port1', 'svr_ip2:svr_port2', ...;
STOP SERVER
是最安全的隔离命令。STOP SERVER
不但可以将业务流量从该节点上切走,实现该节点与业务流量隔离的效果,还能保证除被隔离节点以外的其他节点依然能够构成 Paxos 多数派,从而可以安全的对被隔离节点执行任何动作,例如 pstack、调整日志级别等,甚至停止进程。STOP SERVER
适用于需要故障隔离和停机运维的场景,是故障隔离和运维变更首选的隔离命令。
为了保证成功执行后可以安全的对被隔离节点执行任何动作,STOP SERVER
命令前置检测比较严格,通过内部各种状态检查,保证目标节点即使停止进程后,集群剩余可用节点的副本仍然能够构成 Paxos 多数派,从而不影响数据库服务的连续性。
STOP SERVER
命令限制如下:
-
不允许同时有多个 Zone 的节点被 Stop,如果同时 Stop 了多个 Zone 的节点,或者已经有其他 Zone 的节点被 Stop,则报错
-4660,cannot stop server or stop zone in multiple zones
。如果遇到该错误信息,可以通过查询DBA_OB_SERVERS
和DBA_OB_ZONES
视图,确认是否存在多个 Zone 的节点被 Stop。 -
STOP SERVER
命令通过检查所有租户的所有日志流的 Paxos 成员列表,确认除了目标节点和其他非可用节点外,剩余节点上的副本是否依然能够构成 Paxos 多数派。如果不能构成多数派,则不允许执行Stop Server
操作。-
非可用节点包括:
INACTIVE
、Stopped
(ACTIVE
状态且stop_time
字段大于 0)及DELETING
状态的节点。 -
为了检查日志流的 Paxos 成员列表,要求所有日志流都有 Leader,如果发现日志流没有 Leader,则报错
-4179
,并且展示有问题的日志流信息。例如:租户
1001
的 1 号日志流没有 Leader,则报错信息为Tenant(1001) LS(1) has no leader, stop server not allowed
。如果遇到该错误信息,可以通过查询GV$OB_LOG_STAT
视图确认日志流的 Leader 副本信息,排查 Leader 副本不正常的问题。 -
如果租户的 Locality 属性变更命令与
STOP SERVER
命令并发执行,为了防止误判,禁止在 Locality 变更过程中 Stop 节点。例如:租户
1001
正在变更 Locality 减少一个副本,日志流的成员列表正在从 A、B、C 变为 A、B,此时如果需要 Stop B 节点,STOP SERVER
命令可能误判 B 节点可以被 Stop,从而与减少副本操作冲突。为了避免误判,STOP SERVER
命令会报错-4179
,并且展示正在变更的租户信息Tenant(1001) locality is changing, stop server not allowed
。如果遇到该错误信息,可以通过查询DBA_OB_TENANTS
视图,确认是否存在租户 Locality 变更操作。 -
在排除了目标节点和其他非可用节点后,如果剩余节点上的副本不能满足多数派,则报错
-4179
,并且展示有问题的日志流信息。例如:租户
1001
的 1 号日志流在 Stop 节点后不能满足多数派,则报错信息为Tenant(1001) LS(1) has no enough valid paxos member after stop server, stop server not allowed
。如果遇到该错误信息,可以通过查询GV$OB_LOG_STAT
视图,确认日志流的成员列表和副本信息是否满足多数派。
-
-
STOP SERVER
保证成功执行后,还能够对被隔离节点执行任何侵入性动作。即剩余可用节点上的副本在满足多数派的前提下,还要保证剩余可用节点中的多数派副本的日志是同步的,使得被隔离节点即使停止进程后,剩余节点的日志依然能够形成多数派。-
日志同步判断条件:对比日志流的 Follower 副本和 Leader 副本的最新日志位点,日志位点差距在 5 秒以内即认为日志是同步的。可以通过查询
GV$OB_LOG_STAT
视图的END_SCN
字段,获取指定日志流的各个副本的最新日志位点。 -
如果不满足该条件,则报错
-4179
,并且展示有问题的日志流信息。例如:租户
1001
的 1 号日志流日志不同步,则报错信息为Tenant(1001) LS(1) log not sync, stop server not allowed
。如果遇到该错误信息,可以通过查询GV$OB_LOG_STAT
视图的END_SCN
字段确认日志流副本同步情况。
# 获取指定日志流副本的最新日志位点信息,并转换成时间戳形式 obclient [(none)]> SELECT SCN_TO_TIMESTAMP(END_SCN) FROM GV$OB_LOG_STAT WHERE TENANT_ID = 1001 and LS_ID = 1;
-
STOP SERVER
是最安全的隔离命令,但同时它的前置条件也是最严格的。在实际应用中,特别是故障应急场景下,可能无法完全满足上述前置条件,进而导致 STOP SERVER
命令无法执行成功。因此 OceanBase 数据库提供了另外两种节点隔离命令,FORCE STOP SERVER
和 ISOLATE SERVER
。他们不同程度的放松了前置检查,减少了限制,从而在更多场景下能够成功隔离节点,但节点被隔离后的操作有所限制。任何场景下都应该首选 STOP SERVER
命令,STOP SERVER
无法成功的情况下可以选择弱化版本的节点隔离命令,但弱化版本的节点隔离后能够执行的操作会有所限制。
FORCE STOP SERVER
相比于 STOP SERVER
命令,FORCE STOP SERVER
跳过了日志同步检查。FORCE STOP SERVER
命令能够保证将业务流量从被隔离节点上切走,但不能保证被隔离节点能够安全的停止进程。强行停止进程后可能破坏 Paxos 多数派,从而影响数据库服务的连续性。
FORCE STOP SERVER
的典型应用场景:A、B、C 三个节点,B 节点的副本日志存在较大延迟,例如 1 个小时。此时节点 C 出现硬件异常需要停机运维。为了保证隔离后能够安全的停止进程,我们首选 STOP SERVER
命令隔离节点,但由于 B 节点的副本日志存在较大延迟,STOP SERVER
命令无法执行成功。我们只能退而其次选择 FORCE STOP SERVER
命令来隔离节点,首先避免硬件异常对业务流量造成影响。然后排查 B 节点日志延迟的原因,待 B 节点日志实时后再次尝试执行 STOP SERVER
命令,成功执行后可以安全的进行停机运维。
obclient [(none)]> ALTER SYSTEM FORCE STOP SERVER 'svr_ip1:svr_port1', 'svr_ip2:svr_port2', ...;
警告
FORCE STOP SERVER
仅仅适用于除了待隔离节点外存在其他节点日志延迟的场景,此时隔离节点的目的仅仅是故障隔离,不能进行任何会造成进程停止的侵入性动作。否则会破坏 Paxos 多数派,造成租户无主,影响数据库服务的连续性。
ISOLATE SERVER
相比于 STOP SERVER
和 FORCE STOP SERVER
,ISOLATE SERVER
的前置检查最为宽松,响应速度最快。它不保证安全性,即不保证目标节点下线后,集群剩余节点的副本可以组成 Paxos 多数派继续提供服务。
obclient [(none)]> ALTER SYSTEM ISOLATE SERVER 'svr_ip1:svr_port1', 'svr_ip2:svr_port2', ...;
ISOLATE SERVER
命令前置检查放松逻辑如下:
-
ISOLATE SERVER
命令不再限制多个 Zone 的节点同时隔离,如果已经有其他 Zone 的节点被隔离(执行任何一种隔离命令),也可以执行ISOLATE SERVER
命令。典型场景:集群有三个 Zone(Z1、Z2、Z3),Z1 和 Z3 各自一个节点出现故障,需要隔离。Z1 故障节点隔离成功后,如果采用
STOP SERVER
或者FORCE STOP SERVER
命令继续隔离 Z3 故障节点,会报错不允许同时隔离多个 Zone。此时仅能执行ISOLATE SERVER
命令,将业务流量从故障节点上切走,隔离后不能进行任何会造成进程停止的侵入性动作。 -
ISOLATE SERVER
命令不再检查日志流副本的多数派和日志同步情况,即使不满足相应条件,也可以执行ISOLATE SERVER
命令。典型场景:日志流初始的 Paxos 成员列表为 A、B、C 三个节点,C 节点机器宕机后永久下线,日志流的成员列表变更为 A、B,处于缺副本状态。此时如果 B 节点发生硬件故障并希望隔离该节点,
STOP SERVER
和FORCE STOP SERVER
均会失败,报错为剩余副本不满足多数派。此时仅能执行ISOLATE SERVER
命令,将业务流量从故障节点上切走,隔离后不能进行任何会造成进程停止的侵入性动作。
ISOLATE SERVER
命令限制如下:
当出现多个 Zone 节点被隔离时,ISOLATE SERVER
会检查所有租户的 Primary Zone 属性,要求不能同时隔离一个租户 Primary Zone 所在地域的所有 Zone 的节点,以防止租户的读写服务切到其他地域,进而业务请求跨城访问导致耗时大幅增加。
可以通过 DBA_OB_TENANTS
视图检查租户的 Primary Zone 属性,结合 DBA_OB_ZONES
和 DBA_OB_SERVERS
视图中已经隔离的 Zone 和节点的信息,确认是否打破上述限制条件。
警告
ISOLATE SERVER
仅仅适用于除了待隔离节点外存在其他节点状态异常的场景,此时隔离节点的目的仅仅是故障隔离,不能进行任何会造成进程停止的侵入性动作。否则会破坏 Paxos 多数派,造成租户无主,影响数据库服务的连续性。
总结
任何场景下都应该首选 STOP SERVER
命令,成功执行后除了达成故障隔离的目的,还可以保证能够安全的对被隔离节点执行任何应急动作和运维动作。STOP SERVER
无法成功的情况下可以选择弱化版本的节点隔离命令,但弱化版本的节点隔离后不能保证能够安全的执行侵入性动作。
FORCE STOP SERVER
适用于除了待隔离节点外存在其他节点日志延迟的场景,ISOLATE SERVER
适用于除了待隔离节点外存在其他节点状态异常的场景。此时隔离节点的目的仅仅是故障隔离,不能进行任何会造成进程停止的侵入性运维动作,否则会破坏 Paxos 多数派,造成租户无主,影响数据库服务的连续性。
替换节点
替换节点适用于硬件故障场景、容量场景(不同规格机器替换),替换后集群的节点数量不变。替换节点是一套运维操作的组合:即先添加新节点并迁移副本,然后再删除旧节点,整体时间较长。
操作步骤
-
使用
root
用户登录到集群的sys
租户。连接示例如下,连接数据库时请以实际环境为准。
obclient -h10.xx.xx.xx -P2883 -uroot@sys#obdemo -p***** -A
有关更加详细的连接数据库的操作指引,参见 连接数据库概述(MySQL 模式) 和 连接数据库概述(Oracle 模式)。
-
在待替换节点所在的 Zone 上添加新节点。
添加新节点的详细操作请参见 添加节点。
-
将旧节点上的 Unit 迁移到新节点。
-
查询
DBA_OB_SERVERS
视图获取待替换节点的相关信息。查询示例如下:
obclient [(none)]> SELECT * FROM oceanbase.DBA_OB_SERVERS; +-------------+----------+----+--------------+----------+-----------------+--------+----------------------------+-----------+-----------------------+----------------------------+----------------------------+-------------------------------------------------------------------------------------------+ | SVR_IP | SVR_PORT | ID | ZONE | SQL_PORT | WITH_ROOTSERVER | STATUS | START_SERVICE_TIME | STOP_TIME | BLOCK_MIGRATE_IN_TIME | CREATE_TIME | MODIFY_TIME | BUILD_VERSION | +-------------+----------+----+--------------+----------+-----------------+--------+----------------------------+-----------+-----------------------+----------------------------+----------------------------+-------------------------------------------------------------------------------------------+ | 172.xx.xx.xx| 2882 | 6 | sa128_obv4_2 | 2881 | NO | ACTIVE | 2022-12-30 16:17:03.173519 | NULL | NULL | 2022-12-30 16:08:04.749100 | 2023-01-04 11:48:36.589270 | 4.0.0.0_101000022022120716-0d7927892ad6d830e28437af099f018b0ad9a322(Dec 7 2022 16:22:15) | | 172.xx.xx.xx| 2882 | 4 | sa128_obv4_3 | 2881 | NO | ACTIVE | 2022-12-30 16:36:35.567437 | NULL | NULL | 2022-12-30 16:08:02.755200 | 2023-01-04 14:13:36.976548 | 4.0.0.0_101000022022120716-0d7927892ad6d830e28437af099f018b0ad9a322(Dec 7 2022 16:22:15) | | 172.xx.xx.xx| 2882 | 3 | sa128_obv4_3 | 2881 | NO | ACTIVE | 2022-12-12 12:42:00.054759 | NULL | NULL | 2022-11-03 15:37:09.530894 | 2022-12-22 14:43:26.717736 | 4.0.0.0_101000022022120716-0d7927892ad6d830e28437af099f018b0ad9a322(Dec 7 2022 16:22:15) | | 172.xx.xx.xx| 2882 | 1 | sa128_obv4_1 | 2881 | NO | ACTIVE | 2022-12-12 12:25:17.555651 | NULL | NULL | 2022-11-03 15:37:08.990683 | 2022-12-12 12:25:18.553763 | 4.0.0.0_101000022022120716-0d7927892ad6d830e28437af099f018b0ad9a322(Dec 7 2022 16:22:15) | | 172.xx.xx.xx| 2882 | 2 | sa128_obv4_2 | 2881 | YES | ACTIVE | 2022-12-12 11:46:37.222980 | NULL | NULL | 2022-11-03 15:37:09.490511 | 2022-12-12 11:47:31.075335 | 4.0.0.0_101000022022120716-0d7927892ad6d830e28437af099f018b0ad9a322(Dec 7 2022 16:22:15) | | 172.xx.xx.xx| 2882 | 5 | sa128_obv4_1 | 2881 | NO | ACTIVE | 2022-12-30 16:25:45.420996 | NULL | NULL | 2022-12-30 16:08:03.928478 | 2023-01-04 11:48:36.578231 | 4.0.0.0_101000022022120716-0d7927892ad6d830e28437af099f018b0ad9a322(Dec 7 2022 16:22:15) | +-------------+----------+----+--------------+----------+-----------------+--------+----------------------------+-----------+-----------------------+----------------------------+----------------------------+-------------------------------------------------------------------------------------------+ 6 rows in set
有关
DBA_OB_SERVERS
视图的更多详细信息,请参见 DBA_OB_SERVERS。 -
根据节点 IP 查询待替换的节点的 Unit 列表。
语句如下:
obclient [(none)]> SELECT unit_id FROM oceanbase.DBA_OB_UNITS WHERE SVR_IP = 'svr_ip';
其中,
svr_ip
需要根据实际情况填写待替换节点的 IP 地址。查询示例如下:
obclient [(none)]> SELECT unit_id FROM oceanbase.DBA_OB_UNITS WHERE SVR_IP = '172.xx.xx.xx'; +---------+ | unit_id | +---------+ | 1 | | 1002 | | 1016 | | 1024 | +---------+ 4 rows in set
-
提交 Unit 迁移任务,将旧节点上的 Unit 迁移到同 Zone 的其他节点上。
语句如下:
obclient [(none)]> ALTER SYSTEM MIGRATE UNIT unit_id DESTINATION 'svr_ip:svr_port';
相关参数说明如下:
-
unit_id
:待迁移的 Unit 的 unit_id。 -
svr_ip:svr_port
:新节点的 IP 地址和 RPC 端口号,端口号默认为 2882。
每条命令仅支持迁移一个 Unit,多个 Unit 需要执行多次该命令。
迁移示例如下:
obclient [(none)]> ALTER SYSTEM MIGRATE UNIT 1016 DESTINATION '172.xx.xx.xx:2882';
-
-
查询
oceanbase.DBA_OB_UNIT_JOBS
视图,确认 Unit 的迁移进度。obclient [(none)]> SELECT * FROM oceanbase.DBA_OB_UNIT_JOBS WHERE JOB_TYPE = 'MIGRATE_UNIT'; +--------+--------------+------------+-------------+----------+----------------------------+----------------------------+-----------+---------+----------+------------+------------+-------------+ | JOB_ID | JOB_TYPE | JOB_STATUS | RESULT_CODE | PROGRESS | START_TIME | MODIFY_TIME | TENANT_ID | UNIT_ID | SQL_TEXT | EXTRA_INFO | RS_SVR_IP | RS_SVR_PORT | +--------+--------------+------------+-------------+----------+----------------------------+----------------------------+-----------+---------+----------+------------+------------+-------------+ | 4 | MIGRATE_UNIT | INPROGRESS | NULL | 0 | 2023-01-04 17:22:02.208219 | 2023-01-04 17:22:02.208219 | 1004 | 1006 | NULL | NULL |xx.xx.xx.106| 2882 | +--------+--------------+------------+-------------+----------+----------------------------+----------------------------+-----------+---------+----------+------------+------------+-------------+
如果查询结果为空,则表示 Unit 迁移完成。
更多关于 Unit 迁移的操作及说明,请参见 Unit 迁移。
-
-
等待旧节点上的所有 Unit 迁移完成后,将旧节点删除。
具体操作如下:
-
执行以下命令,删除旧节点。
语句如下:
obclient [(none)]> ALTER SYSTEM DELETE SERVER 'svr_ip:svr_port' [,'svr_ip:svr_port'...] [ZONE [=] 'zone_name']
相关参数说明如下:
-
svr_ip
:表示待删除的旧节点的 IP。 -
port
:表示待删除的旧节点的 RPC 端口,默认为 2882。 -
zone_name
:待删除的旧节点所属的 Zone。
示例如下:
obclient [(none)]> ALTER SYSTEM DELETE SERVER "172.xx.xx.xx:2882" zone='zone1'
-
-
待操作结束后,查询
oceanbase.DBA_OB_SERVERS
视图,确认旧节点是否删除成功。obclient [(none)]> SELECT * FROM oceanbase.DBA_OB_SERVERS;
如果列表中已经查询不到旧节点信息,则表示删除成功。如果列表中仍然有该节点,且该节点的状态为
DELETING
,则表示该节点仍然在删除状态中。
-
启动 Zone
启动 Zone 的操作通常用于允许 Zone 内的所有服务器对外提供服务的场景。
背景信息
启动 Zone 通常使用在以下场景:
-
添加了新的 Zone,且该 Zone 的状态为
INACTIVE
,当前需要使用该 Zone 内的服务器。 -
当前 Zone 因业务原因被隔离,且该 Zone 的状态为
INACTIVE
,需要执行启动 Zone 操作使 Zone 解除隔离。
操作步骤
-
使用
root
用户登录到集群的sys
租户。连接示例如下,连接数据库时请以实际环境为准。
obclient -h10.xx.xx.xx -P2883 -uroot@sys#obdemo -p***** -A
有关更加详细的连接数据库的操作指引,参见 连接数据库概述(MySQL 模式) 和 连接数据库概述(Oracle 模式)。
-
执行以下命令,启动 Zone。
语句如下:
obclient [(none)]> ALTER SYSTEM START ZONE zone_name;
其中,
zone_name
为待启动的 Zone 的名称。每条语句每次仅支持启动一个 Zone。示例如下:
obclient [(none)]> ALTER SYSTEM START ZONE zone4; Query OK, 0 rows affected
-
操作成功后,可以查询
DBA_OB_ZONES
视图进行确认。obclient [(none)]> SELECT * FROM oceanbase.DBA_OB_ZONES; +-------+----------------------------+----------------------------+--------+-----+----------+-----------+ | ZONE | CREATE_TIME | MODIFY_TIME | STATUS | IDC | REGION | TYPE | +-------+----------------------------+----------------------------+--------+-----+----------+-----------+ | zone1 | 2022-12-20 17:50:17.168745 | 2022-12-20 17:50:40.801054 | ACTIVE | HZ0 | hangzhou | ReadWrite | | zone2 | 2022-12-20 17:50:17.168745 | 2022-12-20 17:50:40.809504 | ACTIVE | HZ0 | hangzhou | ReadWrite | | zone3 | 2022-12-20 17:50:17.169804 | 2023-01-30 17:34:11.228474 | ACTIVE | HZ1 | hangzhou | ReadWrite | | zone4 | 2023-01-06 15:30:30.887362 | 2023-01-31 13:47:56.107429 | ACTIVE | hz1 | hangzhou | ReadWrite | +-------+----------------------------+----------------------------+--------+-----+----------+-----------+ 4 rows in set
根据查询结果可以看到,Zone 的状态从
INACTIVE
变为ACTIVE
,表示 Zone 启动成功。
添加 Zone
添加 Zone 通常用于集群的扩容场景中。
操作步骤
-
使用
root
用户登录到集群的sys
租户。连接示例如下,连接数据库时请以实际环境为准。
obclient -h10.xx.xx.xx -P2883 -uroot@sys#obdemo -p***** -A
有关更加详细的连接数据库的操作指引,参见 连接数据库概述(MySQL 模式) 和 连接数据库概述(Oracle 模式)。
-
执行以下命令,在集群中添加 Zone。
语句如下:
obclient [(none)]> ALTER SYSTEM ADD ZONE zone_name [IDC [=] 'idc_name', REGION [=] 'region_name', ZONE_TYPE [=] 'ReadWrite'];
相关参数说明如下:
-
zone_name
:待添加的 Zone 的名称,每条语句每次仅支持添加一个 Zone。如果需要添加多个 Zone,需要重复执行该语句。 -
idc_name
:指定 Zone 所在机房的名称。如果不指定,默认为空。 -
region_name
:指定 Zone 所在 Region 的名称,如果不指定,默认值为default_region
。 -
ZONE_TYPE
:指定 Zone 的类型,当前版本仅支持读写 Zone(ReadWrite
)。如果不指定,默认为读写 Zone。
在集群中增加
zone4
的示例如下:obclient [(none)]> ALTER SYSTEM ADD ZONE zone4 IDC 'hz1', REGION 'hangzhou';
-
-
操作成功后,可以查询
oceanbase.DBA_OB_ZONES
视图进行确认。obclient [(none)]> SELECT * FROM oceanbase.DBA_OB_ZONES; +-------+----------------------------+----------------------------+----------+-----+----------+-----------+ | ZONE | CREATE_TIME | MODIFY_TIME | STATUS | IDC | REGION | TYPE | +-------+----------------------------+----------------------------+----------+-----+----------+-----------+ | zone1 | 2022-12-20 17:50:17.168745 | 2022-12-20 17:50:40.801054 | ACTIVE | HZ0 | hangzhou | ReadWrite | | zone2 | 2022-12-20 17:50:17.168745 | 2022-12-20 17:50:40.809504 | ACTIVE | HZ0 | hangzhou | ReadWrite | | zone3 | 2022-12-20 17:50:17.169804 | 2022-12-20 17:50:40.815833 | ACTIVE | SH0 | shanghai | ReadWrite | | zone4 | 2023-01-06 14:57:18.775946 | 2023-01-06 14:57:18.776974 | INACTIVE | hz1 | hangzhou | ReadWrite | +-------+----------------------------+----------------------------+----------+-----+----------+-----------+ 4 rows in set
查询结果中有新添加的 Zone,则表示添加 Zone 成功,新添加成功的 Zone 的状态为
INACTIVE
。有关
DBA_OB_ZONES
视图的更多详细信息,请参见 oceanbase.DBA_OB_ZONES。 -
添加 Zone 后,如果需要使用该 Zone,还需要启动 Zone,使 Zone 的状态变为
ACTIVE
。语句如下:
obclient [(none)]> ALTER SYSTEM START ZONE zone_name;
其中,
zone_name
为待启动的 Zone 的名称。示例如下:
obclient [(none)]> ALTER SYSTEM START ZONE zone4; Query OK, 0 rows affected obclient [(none)]> SELECT * FROM oceanbase.DBA_OB_ZONES; +-------+----------------------------+----------------------------+--------+-----+----------+-----------+ | ZONE | CREATE_TIME | MODIFY_TIME | STATUS | IDC | REGION | TYPE | +-------+----------------------------+----------------------------+--------+-----+----------+-----------+ | zone1 | 2022-12-20 17:50:17.168745 | 2022-12-20 17:50:40.801054 | ACTIVE | HZ0 | hangzhou | ReadWrite | | zone2 | 2022-12-20 17:50:17.168745 | 2022-12-20 17:50:40.809504 | ACTIVE | HZ0 | hangzhou | ReadWrite | | zone3 | 2022-12-20 17:50:17.169804 | 2023-01-30 17:34:11.228474 | ACTIVE | HZ1 | hangzhou | ReadWrite | | zone4 | 2023-01-06 15:30:30.887362 | 2023-01-31 13:47:56.107429 | ACTIVE | hz1 | hangzhou | ReadWrite | +-------+----------------------------+----------------------------+--------+-----+----------+-----------+ 4 rows in set
根据示例结果可知,成功启动 Zone 后,新添加的 Zone 的状态变为
ACTIVE
。
删除 Zone
删除 Zone 通常用于集群缩容的场景中。
前提条件
删除 Zone 前,需要确认以下事项:
-
请确认该 Zone 下已不存在节点,查看 Zone 内节点的相关操作可参见 查看节点。
-
请确认该 Zone 已停止。
停止 Zone 的语句如下:
obclient [(none)]> ALTER SYSTEM STOP ZONE zone_name;
其中,
zone_name
为待停止的 Zone 的名称。每条语句每次仅支持停止一个 Zone。示例如下:
obclient [(none)]> ALTER SYSTEM STOP ZONE zone4;
操作步骤
-
使用
root
用户登录到集群的sys
租户。连接示例如下,连接数据库时请以实际环境为准。
obclient -h10.xx.xx.xx -P2883 -uroot@sys#obdemo -p***** -A
有关更加详细的连接数据库的操作指引,参见 连接数据库概述(MySQL 模式) 和 连接数据库概述(Oracle 模式)。
-
执行以下命令,删除集群中的 Zone。
语句如下:
obclient [(none)]> ALTER SYSTEM DELETE ZONE zone_name;
其中,
zone_name
表示待删除的 Zone 的名称。每条语句每次仅支持删除一个 Zone。如果需要删除多个 Zone,则需要重复执行该语句。删除集群中的
zone4
的示例如下:obclient [(none)]> ALTER SYSTEM DELETE ZONE zone4;
-
操作成功后,可以查询
oceanbase.DBA_OB_ZONES
视图进行确认。obclient [(none)]> SELECT * FROM oceanbase.DBA_OB_ZONES; +-------+----------------------------+----------------------------+--------+-----+----------+-----------+ | ZONE | CREATE_TIME | MODIFY_TIME | STATUS | IDC | REGION | TYPE | +-------+----------------------------+----------------------------+--------+-----+----------+-----------+ | zone1 | 2022-12-20 17:50:17.168745 | 2022-12-20 17:50:40.801054 | ACTIVE | HZ0 | hangzhou | ReadWrite | | zone2 | 2022-12-20 17:50:17.168745 | 2022-12-20 17:50:40.809504 | ACTIVE | HZ0 | hangzhou | ReadWrite | | zone3 | 2022-12-20 17:50:17.169804 | 2022-12-20 17:50:40.815833 | ACTIVE | SH0 | shanghai | ReadWrite | +-------+----------------------------+----------------------------+--------+-----+----------+-----------+ 3 rows in set
查询结果中没有该 Zone,则表示删除 Zone 成功。
修改 Zone
修改 Zone 主要修改 Zone 所属的 Region 及 IDC 信息。
使用限制
当前不支持修改 Zone 的 ZONE_TYPE
。
操作步骤
-
使用
root
用户登录到集群的sys
租户。连接示例如下,连接数据库时请以实际环境为准。
obclient -h10.xx.xx.xx -P2883 -uroot@sys#obdemo -p***** -A
有关更加详细的连接数据库的操作指引,参见 连接数据库概述(MySQL 模式) 和 连接数据库概述(Oracle 模式)。
-
执行以下命令,修改 Zone 属性。
语句如下:
obclient [(none)]> ALTER SYSTEM {ALTER|CHANGE|MODIFY} ZONE zone_name SET [IDC [=]'idc_name', REGION [=]'region_name'];
相关参数说明如下:
-
{ALTER|CHANGE|MODIFY}
:表示ALTER
、CHANGE
、MODIFY
三者的功能相同,可以使用任意一个关键字来修改 Zone 属性。 -
zone_name
:表示待修改的 Zone 的名称。每条语句每次仅支持修改一个 Zone。 -
idc_name
:指定 Zone 所在机房的名称。 -
region_name
:指定 Zone 所在 Region 的名称。
例如,将当前集群所处的区域(Region)修改为
shanghai
,所处的机房修改为sh1
的示例如下:obclient [(none)]> ALTER SYSTEM ALTER ZONE zone4 SET REGION 'shanghai',IDC 'sh1';
-
-
操作成功后,可以查询
oceanbase.DBA_OB_ZONES
视图进行确认。obclient [(none)]> SELECT * FROM oceanbase.DBA_OB_ZONES; +-------+----------------------------+----------------------------+----------+-----+----------+-----------+ | ZONE | CREATE_TIME | MODIFY_TIME | STATUS | IDC | REGION | TYPE | +-------+----------------------------+----------------------------+----------+-----+----------+-----------+ | zone1 | 2022-12-20 17:50:17.168745 | 2022-12-20 17:50:40.801054 | ACTIVE | HZ0 | hangzhou | ReadWrite | | zone2 | 2022-12-20 17:50:17.168745 | 2022-12-20 17:50:40.809504 | ACTIVE | HZ0 | hangzhou | ReadWrite | | zone3 | 2022-12-20 17:50:17.169804 | 2022-12-20 17:50:40.815833 | ACTIVE | SH0 | shanghai | ReadWrite | | zone4 | 2023-01-06 15:25:07.190559 | 2023-01-06 15:25:29.281242 | INACTIVE | sh1 | shanghai | ReadWrite | +-------+----------------------------+----------------------------+----------+-----+----------+-----------+ 4 rows in set
隔离 Zone
为了实现 OceanBase 数据库的高级别容灾功能,我们引入了 Zone 的概念。Zone 是一个逻辑概念,一般是具有相似容灾属性的一组节点的组合。从物理层面来讲,一个 Zone 通常是一个独立的物理部署单元,可以是一个数据中心(IDC)或者云上的一个可用区,也可以是一个单独的机架(Rack)。通过将 OceanBase 集群部署于多个 Zone (通常至少 3 个 Zone),实现单个 Zone 故障时的故障隔离及快速恢复。
当需要进行 Zone 级容灾或者 Zone 级运维变更时,可以隔离 Zone。隔离后,新的读写请求不会路由到该 Zone 内的节点上,从而可以隔离故障或者无损的执行运维变更动作。
-
故障隔离场景:例如多机房部署架构下,某机房内有交换机异常,此时部分节点出现丢包、重传,甚至无主选举。为了快速恢复,可以直接隔离该机房对应的 Zone。
-
运维变更场景:例如 OceanBase 集群升级时采用的轮转升级方案,首先隔离一个 Zone,将用户流量从该 Zone 切到其他 Zone,然后执行升级动作。该 Zone 升级完成后执行 Start 操作恢复流量,再依次升级其他 Zone,从而做到升级对用户透明。
隔离 Zone,只是将用户流量从该 Zone 切走,并没有改变 Paxos 投票成员的数量。不同的隔离命令有不同的安全级别保证,需要根据执行的具体的隔离命令仔细斟酌后续能够安全执行的动作。隔离命令适用于短时间隔离场景,需要持续保持关注,提前做好二次故障的应急预案。如果短时间内恢复不了,可以采用替换 Zone 的方式彻底去除隐患。
隔离 Zone 有以下三种命令,不同的隔离命令有不同的安全级别保证:
-
通过
STOP ZONE
命令隔离 Zone -
通过
FORCE STOP ZONE
命令隔离 Zone -
通过
ISOLATE ZONE
命令隔离 Zone
通过以上命令成功隔离 Zone 后,Zone 的 STATUS
的值变为 INACTIVE
,表示该 Zone 处于隔离状态。
STOP ZONE
命令格式如下:
obclient [(none)]> ALTER SYSTEM STOP ZONE 'zone_name';
STOP ZONE
是最安全的隔离命令。STOP Zone
不但可以将业务流量从该 Zone 切走,实现 Zone 内节点与业务流量隔离的效果,还能保证除被隔离 Zone 以外的其他 Zone 的节点依然能够构成 Paxos 多数派,从而可以安全的对被隔离 Zone 的节点执行任何动作,例如 pstack、调整日志级别等,甚至停止进程。STOP ZONE
适用于需要故障隔离和停机运维的场景,是故障隔离和运维变更首选的隔离命令。
为了保证成功执行后可以安全的对被隔离 Zone 内的节点执行任何动作,STOP ZONE
命令前置检测比较严格,通过内部各种状态检查,保证目标节点即使停止进程后,集群剩余可用节点的副本仍然能够构成 Paxos 多数派,从而不影响数据库服务的连续性。
STOP ZONE
命令限制如下:
-
不允许同时有多个 Zone 以及多个 Zone 的节点被 Stop,如果已经有其他 Zone 或者其他 Zone 的节点被 Stop,则
STOP ZONE
报错-4660,cannot stop server or stop zone in multiple zones
。如果遇到该错误信息,可以通过查询DBA_OB_SERVERS
和DBA_OB_ZONES
,确认是否存在 Zone 或者节点被 Stop。 -
STOP ZONE
命令通过检查所有租户的所有日志流的 Paxos 成员列表,确认除了目标 Zone 节点和其他非可用节点外,剩余节点上的副本是否依然能够构成 Paxos 多数派。如果不能构成多数派,则不允许执行STOP ZONE
操作。-
非可用节点包括
INACTIVE
、stopped
(ACTIVE
状态且stop_time
字段大于 0)及DELETING
状态的节点。 -
为了检查日志流的 Paxos 成员列表,要求所有日志流都有 Leader,如果发现日志流没有 Leader,则报错
-4179
,并且展示有问题的日志流信息。例如:租户
1001
的 1 号日志流没有 Leader,则报错信息为Tenant(1001) LS(1) has no leader, stop zone not allowed
。如果遇到该错误信息,可以通过查询GV$OB_LOG_STAT
视图确认日志流的 Leader 副本信息,排查 Leader 副本不正常的问题。 -
如果租户的 Locality 属性变更与
STOP ZONE
命令并发,为了防止误判,禁止在 Locality 变更过程中STOP ZONE
。例如:租户
1001
正在变更 Locality 减少一个副本,日志流的成员列表正在从 A、B、C 变为 A、B,此时如果需要 Stop B 节点所在的 Zone,STOP ZONE
命令可能误判可以被 Stop,从而与减少副本操作冲突。为了避免误判,STOP ZONE
命令会报错-4179
,并且展示正在变更的租户信息Tenant(1001) locality is changing, stop zone not allowed
。如果遇到该错误信息,可以通过查询DBA_OB_TENANTS
视图,确认是否存在租户 Locality 变更操作。 -
在排除了目标 Zone 节点和其他非可用节点后,如果剩余节点上的副本不能满足多数派,则报错
-4179
,并且展示有问题的日志流信息。例如:租户
1001
的 1 号日志流在STOP ZONE
后不能满足多数派,则报错信息为Tenant(1001) LS(1) has no enough valid paxos member after stop zone, stop zone not allowed
。如果遇到该错误信息,可以通过查询GV$OB_LOG_STAT
视图,确认日志流的成员列表和副本信息是否满足多数派。
-
-
STOP ZONE
保证成功执行后,还能够对被隔离 Zone 内的节点执行任何侵入性动作。即剩余可用节点上的副本在满足多数派的前提下,还要保证剩余可用节点中的多数派副本的日志是同步的,使得被隔离 Zone 内的节点即使停止进程后,剩余节点的日志依然能够形成多数派。-
日志同步判断条件:对比日志流的 Follower 副本和 Leader 副本的最新日志位点,日志位点差距在 5 秒以内即认为日志是同步的。可以通过查询
GV$OB_LOG_STAT
视图的END_SCN
字段,获取指定日志流的各个副本的最新日志位点。 -
如果不满足该条件,则报错
-4179
,并且展示有问题的日志流信息。例如:租户
1001
的 1 号日志流日志不同步,则报错信息为Tenant(1001) LS(1) log not sync, stop server not allowed
。如果遇到该错误信息,可以通过查询GV$OB_LOG_STAT
视图的END_SCN
字段确认日志流副本同步情况。
# 获取指定日志流副本的最新日志位点信息,并转换成时间戳形式 obclient [(none)]> SELECT SCN_TO_TIMESTAMP(END_SCN) FROM GV$OB_LOG_STAT WHERE TENANT_ID = 1001 and LS_ID = 1;
-
STOP ZONE
是最安全的隔离命令,但同时它的前置条件也是最严格的。在实际应用中,特别是故障应急场景下,可能无法完全满足上述前置条件,进而导致 STOP ZONE
命令无法执行成功。因此 OceanBase 数据库提供了另外两种 Zone 隔离命令:FORCE STOP ZONE
和 ISOLATE ZONE
。他们不同程度的放松了前置检查,减少了限制,从而在更多场景下能够成功隔离 Zone,但 Zone 被隔离后的操作有所限制。任何场景下都应该首选 STOP ZONE
命令,STOP ZONE
无法成功的情况下可以选择弱化版本的 Zone 隔离命令,但弱化版本的 Zone 隔离后能够执行的操作会有所限制。
FORCE STOP ZONE
相比于 STOP ZONE
命令,FORCE STOP ZONE
跳过了日志同步检查。FORCE STOP ZONE
命令能够保证将业务流量从被隔离 Zone 内的节点上切走,但不能保证被隔离 Zone 内的节点能够安全的停止进程。强行停止进程后可能破坏 Paxos 多数派,从而影响数据库服务的连续性。
FORCE STOP ZONE
的典型应用场景:某机房内的服务器或者网络设备出现硬件异常需要停机运维,为了保证隔离后能够安全的停止进程,我们首选 STOP ZONE
命令隔离机房对应的 Zone,但其他 Zone 内的节点的副本日志存在较大延迟,STOP ZONE
命令无法执行成功。我们只能退而其次选择 FORCE STOP ZONE
命令来隔离 Zone,首先避免硬件异常对业务流量造成影响。然后排查副本日志延迟的原因,待副本日志实时后再次尝试执行 STOP ZONE
命令,成功执行后可以安全的进行停机运维。
obclient [(none)]> ALTER SYSTEM FORCE STOP ZONE zone_name;
注意事项:
-
如果在
FORCE STOP ZONE
之后,目标 Zone 节点仍然继续参与 Paxos 日志同步,明确不会下线目标 Zone 节点,那么可以安全的使用FORCE STOP ZONE
,实现隔离故障以及切换业务流量目的。即使存在部分副本日志不同步,也不会影响服务的连续性。 -
如果用户希望在
FORCE STOP ZONE
之后下线目标节点,那么用户需要关注存在落后副本的日志流情况,确认目标节点下线后,是否影响该日志流提供服务,用户还可以通过查询GV$OB_LOG_STAT
视图评估服务影响时间。
警告
FORCE STOP ZONE
仅仅适用于除了待隔离 Zone 内节点外存在其他节点日志延迟的场景,此时隔离 Zone 的目的仅仅是故障隔离,不能进行任何会造成进程停止的侵入性动作。否则会破坏 Paxos 多数派,造成租户无主,影响数据库服务的连续性。
ISOLATE ZONE
相比于 STOP ZONE
和 FORCE STOP ZONE
,ISOLATE ZONE
的前置检查最为宽松,响应速度最快。它不保证安全性,即不保证目标 Zone 内的节点下线后,集群剩余节点的副本可以组成 Paxos 多数派继续提供服务。
obclient [(none)]> ALTER SYSTEM ISOLATE ZONE zone_name;
ISOLATE ZONE
命令前置检查放松逻辑如下:
-
ISOLATE ZONE
命令不再限制多个 Zone 的节点同时隔离,如果已经有其他 Zone 的节点被隔离(执行任何一种隔离命令),也可以执行ISOLATE ZONE
命令。典型场景:集群有三个 Zone(Z1、Z2、Z3),Z1 和 Z3 各自一个节点出现故障,需要隔离。Z1 故障节点隔离成功后,如果采用
STOP ZONE
或者FORCE STOP ZONE
命令继续隔离 Z3 故障节点,会报错不允许同时隔离多个 Zone。此时仅能执行ISOLATE ZONE
命令,将业务流量从故障节点上切走,隔离后不能进行任何会造成进程停止的侵入性动作。 -
ISOLATE ZONE
命令不再检查日志流副本的多数派和日志同步情况,即使不满足相应条件,也可以执行ISOLATE ZONE
命令。典型场景:日志流初始的 Paxos 成员列表为 A、B、C 三个节点,C 节点机器宕机后永久下线,日志流的成员列表变更为 A、B,处于缺副本状态。此时如果 B 节点发生硬件故障并希望隔离该节点所在的 Zone,
STOP ZONE
和FORCE STOP ZONE
均会失败,报错为剩余副本不满足多数派。此时仅能执行ISOLATE ZONE
命令,将业务流量从故障节点上切走,隔离后不能进行任何会造成进程停止的侵入性动作。
ISOLATE ZONE
命令限制如下:
当出现多个 Zone 节点被隔离时,ISOLATE ZONE
会检查所有租户的 Primary Zone 属性,要求不能同时隔离一个租户 Primary Zone 所在地域的所有 Zone,以防止租户的读写服务切到其他地域,进而业务请求跨城访问导致耗时大幅增加。
可以通过 DBA_OB_TENANTS
视图检查租户的 Primary Zone 属性,结合 DBA_OB_ZONES
和 DBA_OB_SERVERS
视图中已经隔离的 Zone 和节点的信息,确认是否打破上述限制条件。
警告
ISOLATE ZONE
仅仅适用于除了待隔离 Zone 内节点外存在其他节点状态异常的场景,此时隔离 Zone 的目的仅仅是故障隔离,不能进行任何会造成进程停止的侵入性动作。否则会破坏 Paxos 多数派,造成租户无主,影响数据库服务的连续性。。
总结
任何场景下都应该首选 STOP ZONE
命令,成功执行后除了达成故障隔离的目的,还可以保证能够安全的对被隔离 Zone 内节点执行任何应急动作和运维动作。STOP ZONE
无法成功的情况下可以选择弱化版本的 Zone 隔离命令,但弱化版本的 Zone 隔离后不能保证能够安全的执行侵入性动作。
FORCE STOP ZONE
适用于除了待隔离 Zone 内节点外存在其他节点日志延迟的场景,ISOLATE ZONE
适用于除了待隔离 Zone 内节点外存在其他节点状态异常的场景。此时隔离 Zone 的目的仅仅是故障隔离,不能进行任何会造成进程停止的侵入性运维动作,否则会破坏 Paxos 多数派,造成租户无主,影响数据库服务的连续性。