首批通过分布式安全可靠测评,为关键业务系统打造
迁移复制问题排查
更新时间:2024-07-23 05:41
背景
通过以下手段,我们可以主动触发副本的迁移、复制、删除、类型变换等行为。
admin 命令:
alter system change/drop/add/migrate命令。locality 变更:支持 tenant/table/tablegroup 级别的 locality 变更。
unit 迁移:
alter system migrate unit命令。delete server:主要是后台发起 unit 迁移操作。
通过相关命令会异步触发后台的相关 partition 的任务,下面给出相关 partition 任务执行问题的执行思路。
相关配置项
以下是控制迁移复制速度的相关配置项,可视实际情况进行调节。
| 参数 | 默认值 | 解释 |
|---|---|---|
| data_disk_usage_limit_percentage | 90 | 允许迁入副本或者迁入 unit 的磁盘水位最大值,如果超过这个值,加副本或者迁移 unit 任务就会暂停,__all_server 表的那个 server 的 block_migrate_in_time会大于 0。 |
| migration_disable_time | 3600 | RS 在因为磁盘水位高暂停任务后重试任务的时间间隔,如果遇到 data_disk_usage_limit_percentage 过低需要调大的情况,那么调大 data_disk_usage_limit_percentage后,如果想 RS 尽快调度复制迁移,需要调小此值。 |
| sys_bkgd_net_percentage | 60 | 复制或者迁移使用本机带宽的百分比,如果本机是万兆,那么最多使用10000MB * 60%,如果是千兆,那么最多使用 1000MB * 60%。 |
| balancer_idle_time | 5m | 控制 RS 负载均衡任务调度间隔。 |
| server_data_copy_in_concurrency | 2 | 表示单个 OBServer,作为目标端(包括复制,迁移,类型转换的目标端)同时执行的任务数,主要是在 RS 端限流。 |
| server_data_copy_out_concurrency | 2 | 表示单个 OBServer,作为源端(包括复制,迁移,类型转换的源端)同时执行的任务数,主要是在 RS 端限流。 |
| data_copy_concurrency | 20 | 表示集群中同时执行的任务(包括复制,迁移,类型转换)的上限,主要是在 RS 端限流。 |
| server_permanent_offline_time | 3600s | 表示该机器上面的副本永久下线时间,时间未到的话,unit 迁移不了。 |
| migrate_concurrency | 10 | |
| enable_rebalance | true | 负载均衡开关,部分版本部分操作依赖该开关打开。 |
| enable_rereplication | true | 补副本开关,部分版本部分操作依赖该开关打开。 |
| __balance_controller | "" | 用于精细化控制 RS 负载均衡行为,一般为空。非空场合部分负载均衡会不运行
注意该配置项一旦打开,除配置项显示指定的负载均衡操作外,其余负载均衡操作一概无法发起。运维修改该配置项时,在相关运维操作结束后记得将该配置项重置为空。 |
| enable_auto_leader_switch | true | leader 均衡开关。 |
相关内部表
| 表名称 | 说明 |
|---|---|
| __all_server | 关注 block_migrate_in_time,如果大于 0 证明副本迁入已经卡住,需要释放空间或者调大 data_disk_usage_limit_percentage。关注 status、start_service_time:status 非 active,或者 start_service_time为 0,需要重点关注。 |
| __all_tenant | 关注 primary_zone、locality、previous_locality。若 previous_locality有值,说明当前的 locality 变更操作为previous_locality->locality。 |
| gv$unit / __all_unit | gv$unit可以看某个租户的 unit 分布。__all_unit可确认集群是否有 unit 迁移任务(migrate_from_svr_ip、migrate_from_svr_port 有值)。 |
| __all_rootservice_job | 记录迁移 unit、变 locality 等单条 SQL 对应的任务状态。 |
| __all_rootservice_event_history | RS 负载均衡任务基本上都会记录相关事件(可能缺失),可以看到相关负载均衡任务发起的时间及结果。 |
| __all_virtual_replica_task | RS 视图,该表有值说明需要发起相关 partition 副本的 add、drop、type_transform操作。缺副本、locality 变更场景可以查看待发起、完成的相关负载均衡任务。 |
| __all_virtual_rebalance_task_stat | 这个是 RS 的虚拟表,表示集群中当前已经生成的所有任务(复制,迁移,类型转换)。该表有一列 is_scheduled,is_scheduled=Yes表示任务已经下发到 OBServer 开始执行,is_scheduled=No表示任务还没有被下发到 OBServer 执行。 |
| __all_virtual_sys_task_status | 这个是 OBServer 的虚拟表,内容是已经下发到 OBServer 端执行的任务。 |
排查思路
负载均衡任务的通用排查思路大致有以下三步:
- 确认配置项。
- 需关注非缺省的配置项取值。
- 确认负载均衡逻辑相关开关是否打开:
enable_rebalance、enable_rereplication、__balance_controller、enable_auto_leader_switch。
- 确认内部表。
- 看集群分布、机器状态:
__all_server、__all_tenant、gv$unit/__all_unit。 - 确定负载均衡任务类型:
__all_rootservice_job。 - 确定分区是否无主(无主无法发起部分负载均衡任务):
__all_virtual_partition_table。 - 确定分区分布(是否缺副本、多副本):
__all_replica_task。 - 确定是否有正在执行的负载均衡任务(同一个分区只能有一个负载均衡任务):
__all_rootservice_event_history。 - 确定负载均衡任务是否调度:
__all_virtual_rebalance_task_stat、__all_virtual_sys_task_status。 - 确定负载均衡任务结果:
__all_rootservice_event_history。
- 看集群分布、机器状态:
- 看日志。
- 排查 RS 没调度负载均衡的原因:
grep "balancer" rootservice.log并按线程号展开。 - 排查具体负载均衡任务执行报错的原因:按 pkey、错误码
grep observer.log。
- 排查 RS 没调度负载均衡的原因:
确定问题 partition
无论是通过何种方式发起的负载均衡任务,如果怀疑有问题的话,需要先定位到有问题的 partition。根据不同的场景,我们通过不同的方式获取有问题的 partition。
Unit 迁移
执行如下命名查看当前是否有 unit 迁移任务,非空表示有。
select * from __all_unit where migrate_from_svr_ip != "" or migrate_from_svr_port != "";
select * from __all_virtual_partition_table where unit_id = xxx and svr_ip = "yyy";
unit_id填上条查询的unit_id,以获取待迁移的 partition key。svr_ip填上条查询的migrate_from_svr_ip。
Delete Server
执行如下命令查看 server 是否下线。非空表示server没有下线完成。
select * from __all_server where svr_ip = "xxx" and svr_port = yyy;
执行如下命令以获取待下线的 partition key。svr_ip/svr_port填上述 server 地址。
select * from __all_virtual_partition_table where svr_ip = "xxx" and svr_port = yyy;
Admin 命令
admin 命令通常需要显式指定 partition key,partition key 格式形如 partition_id%partition_cnt@table_id。
Locality 变更
执行如下命令,非空表示对应租户正在做 locality 变更。
select tenant_id, tenant_name, locality, previous_locality from __all_tenant where previous_locality != "";
执行如下命令获取需要增、删、类型转换的分区负载均衡任务。
select * from __all_virtual_replica_task where tenant_id = xxx;
补副本
集群缺副本的时候,RS 会发起补副本操作,一个通用的检查租户副本分布和 locality 是否匹配的语句如下所示。
select * from __all_virtual_replica_task where tenant_id = xxx;
- cmd_type一般有以下几种可能的取值:
- ADD_REPLICA:需要补副本。
- MEMBER_CHANGE:需要将paxos成员移除。
- REMOVE_NON_PAXOS_REPLICA:需要删除副本。
- TYPE_TRANSFORM:需要发起副本类型转换任务。
查看 RS 任务调度状态
查看 job 状态
外部发起的命令都会记录到 __all_rootservice_job中,可先确认任务是否发起及相关状态(该表状态可能不准)。
select * from __all_rootservice_job order by gmt_create desc limit 10;
确认任务被调度或排队中
select * from __all_virtual_rebalance_task_stat;
is_scheduled : yes 表示任务正在调度,否则表示在排队。
若没看到负载均衡队列有任务,可以看相关配置项是否设置合理,及联系技术支持排查未调度的原因。
确认负载均衡任务执行情况
执行如下语句定位到具体的分区负载均衡任务获得 table_id或 partition_id。
select * from __all_rootservice_event_history where value1 like "%table_id%partition_id%" order by gmt_create desc limit 10;
如下图所示,表示某个分区迁移失败报 -4029:

一般 event 表里有明确报错的,可以按 pkey、错误码搜 source、destination 机器对应时间点的 observer.log 或 rootservice.log,以获取更详细的报错信息。
终极的手段是去 RS 所在机器 grep "root_balancer" rootservice.log 拿到线程号 LWP_ID 后,grep "LWP_ID" rootservice.log 看 RS 的负载均衡线程正在做什么。
查看存储层调度状态
查看 OBServer 任务调度状态
select * from __all_virtual_sys_task_status;
+----------------------------+---------------------------+-------------------------------+---------------+----------+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+
| start_time | task_type | task_id | svr_ip | svr_port | tenant_id | comment | is_cancel |
+----------------------------+---------------------------+-------------------------------+---------------+----------+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+
| 2019-03-01 00:01:01.710589 | group partition migration | YB420BE80B86-00057350CB72EC9F | 11.xxx.xxx.xx | 2882 | 1040 | group partition migration: group_task_id=YB420BE80B86-00057350CB72EC9F partition_count=1 partition_id=0 key={tid:1143492092937043, partition_id:0, part_cnt:0}, op_type=ADD_REPLICA_OP, src="11.xxx.xx.xx:2882", dest="11.xxx.xxx.xx:2882", | 0 |
| 2019-03-01 00:01:01.716896 | partition migration | YB420BBEE129-000582EC67B0BBB5 | 11.xxx.xxx.xx | 2882 | 1040 | single partition migration: group_task_id=YB420BE80B86-00057350CB72EC9F key={tid:1143492092937043, partition_id:0, part_cnt:0}, op_type=ADD_REPLICA_OP, src="11.xxx.xx.xx:2882", dest="11.xxx.xxx.xx:2882", | 0 |
+----------------------------+---------------------------+-------------------------------+---------------+----------+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+
2 rows in set (0.06 sec)
其他常用 SQL
SQL:查询磁盘空间使用,OceanBase 数据库 V2.x 版本需要将内部表换成
__all_virtual_meta_table。SELECT a.zone, a.svr_ip, round(disk_in_use / 1024 / 1024 / 1024, 3) AS disk_used_G, round(disk_total / 1024 / 1024 / 1024, 3) AS disk_total_G, round(disk_in_use / disk_total, 4) * 100 AS disk_used_pct FROM oceanbase.__all_meta_table a, oceanbase.__all_virtual_server_stat b WHERE a.svr_ip = b.svr_ip GROUP BY a.zone, a.svr_ip order by disk_used_pct desc , a.zone, a.svr_ip; +---------------+----------------+-------------+--------------+---------------+ | zone | svr_ip | disk_used_G | disk_total_G | disk_used_pct | +---------------+----------------+-------------+--------------+---------------+ | alipay.et2_9 | 11.190.xxx.xx | 15460.984 | 17305.309 | 89.3400 | | alipay.et2_9 | 11.190.xxx.xx | 15355.619 | 17305.309 | 88.7300 | | alipay.em14_4 | 10.55.xxx.xx | 11304.959 | 12760.816 | 88.5900 | | alipay.et15_8 | 11.232.xx.xx | 7156.662 | 8345.996 | 85.7500 | | alipay.em14_7 | 11.37.xx.xx | 8413.848 | 10995.385 | 76.5200 | | alipay.em14_7 | 11.37.xx.xxx | 8361.656 | 10995.385 | 76.0500 | | alipay.em14_7 | 11.35.x.xxx | 8330.029 | 10995.385 | 75.7600 | | alipay.em14_7 | 11.35.xx.xxx | 8243.814 | 10995.385 | 74.9800 | | alipay.em14_7 | 11.37.xx.xx | 8215.531 | 10995.385 | 74.7200 | | alipay.em14_4 | 11.232.xx.xxx | 9452.061 | 12760.816 | 74.0700 | | alipay.em14_4 | 10.55.xxx.xx | 9436.119 | 12760.816 | 73.9500 | | alipay.em14_4 | 11.233.xx.xxx | 11371.594 | 16176.600 | 70.3000 | | alipay.et15_8 | 11.144.xx.xx | 8194.422 | 12519.936 | 65.4500 | | alipay.et15_8 | 11.232.xxx.xxx | 5412.559 | 8345.996 | 64.8500 | | alipay.et15_8 | 11.232.xx.xxx | 5361.699 | 8345.996 | 64.2400 | | alipay.et15_8 | 11.232.xx.xx | 5358.838 | 8345.996 | 64.2100 | | alipay.et2_9 | 11.190.xxx.xx | 10656.492 | 17305.309 | 61.5800 | | alipay.et15_8 | 11.232.xx.xx | 4147.432 | 8345.996 | 49.6900 | | alipay.et15_8 | 11.149.xxx.xxx | 5932.834 | 12519.936 | 47.3900 | +---------------+----------------+-------------+--------------+---------------+ 19 rows in set (0.04 sec)SQL: 查询 server 复制迁移是不是被 block 了。
select * from __all_server where block_migrate_in_time > 0 \G如果 server 因为磁盘满禁止迁入了,这个 server 的
block_migrate_in_time是非零,而是一个timestamp,转化成实际时间可以看到具体的禁止迁入时间可以通过以下命令尽快解除 block 状态:
alter system set migration_disable_time = "600s";