前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >OB 运维 | OceanBase 单机改三副本:实操手记与深思

OB 运维 | OceanBase 单机改三副本:实操手记与深思

作者头像
爱可生开源社区
发布2025-02-19 23:35:07
发布2025-02-19 23:35:07
14300
代码可运行
举报
运行总次数:0
代码可运行

作者:李锡超,苏商银行DBA,负责数据库和中间件运维和建设。擅长 MySQL、Python、Oracle,爱好骑行、技术研究和分享。

爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本文约 4500 字,预计阅读需要 15 分钟。


近期,在进行 OceanBase 测试时,执行了一次单机转单副本的测试。按照官方文档步骤操作后,发现了不少问题,在此进行总结。

1租户扩容

建议先对 sys 租户进行扩容,这应该是必要步骤,否则扩容后可能是“伪集群”。官方文档似乎遗漏了这一步骤,笔者在后续过程中发现问题,尝试解决时才注意到。

建议在扩容业务租户前执行以下操作:

代码语言:javascript
代码运行次数:0
运行
复制
ALTER RESOURCE POOL sys_pool ZONE_LIST=('zone1','zone2','zone3');
ALTER TENANT sys LOCALITY='F@zone1,F@zone2';
ALTER TENANT sys LOCALITY='F@zone1,F@zone2,F@zone3';

2表的副本管理

根据测试结果,OceanBase 4.X 版本的表副本管理基本自动化,主要基于租户的 PRIMARY_ZONE 等配置。同时,早期版本中很多关于表副本管理的命令在该版本已被废弃。例如:

代码语言:javascript
代码运行次数:0
运行
复制
ALTER TABLE test_t1 set locality = 'F@zone3,F@zone2,F@zone1';
ALTER TABLE test_t1 locality='F,R{all_server}@ZONE1, F,R{all_server}@ZONE2, F,R{all_server}@ZONE3';

执行上述命令时会报错,提示语法错误,需根据 OceanBase 版本查看正确语法。

3表副本分布异常分析

本次测试遇到最大问题是 log_disk_size 参数的设置,导致第一轮测试完全失败,且经过很长时间才找到问题原因。这也是分布式数据库与传统数据库在运维上的典型差异。

完成租户扩容后,通过以下语句检查表的分布:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT tenant_name,database_name, table_name, partition_name, index_name, tablet_id,ls_id,zone,svr_ip,role
FROM OCEANBASE.CDB_OB_TABLE_LOCATIONS a join oceanbase.DBA_OB_TENANTS b
on a.tenant_id=b.tenant_id
WHERE  DATABASE_NAME='MYDB' AND TENANT_NAME='mysql_tenant1'
order by tenant_name,database_name, table_name, partition_name, zone;

SELECT zone,svr_ip,role,count(1)
FROM OCEANBASE.CDB_OB_TABLE_LOCATIONS a join oceanbase.DBA_OB_TENANTS b
on a.tenant_id=b.tenant_id
WHERE  DATABASE_NAME='MYDB' AND TENANT_NAME='mysql_tenant1'
group by zone,svr_ip,role
order by zone;
返回结果
返回结果

返回结果

根据返回结果可知,无论表是否分区,其 LEADER 都只在 zone1、zone2,在 zone3 上全是 FOLLOWER。

确认租户 PRIMARY_ZONE='zone1,zone2,zone3' ,并建立大量表和分区后,均未发现问题。尝试通过建表时指定分区/表的位置,发现相关指令只能在老版本中执行。停止 zone2 进行强制切换,发现 zone2 停止后,所有 LEADER 都迁移到了 zone1,zone3 仍然全是 FOLLOWER。

重新安装 3 节点集群、创建租户并导入测试数据后,问题依旧存在。做如下尝试:

  1. 设置 PRIMARY_ZONE='zone1,zone2,zone3' 不生效,尝试设置 PRIMARY_ZONE=RANDOM,问题未解决。
  2. 再次尝试建立数千个分区,观察分布,问题未解决。
  3. 通过日志跟踪表和分区的创建过程,未看出具体原因,问题未解决。
  4. 查阅资料,检查相关参数,包括 enable_rebalance/enable_transfer 参数,均采用默认值(true),表示会开启自动负载均衡功能。了解到小租户的概念及 LEADER 分布规则,尝试建立多个租户后,问题依旧存在。同时,根据资料提示编写命令尝试切换,但 OceanBase 4.X 中不支持相关语法。
  5. 测试发现 ALTER SYSTEM SWITCH REPLICA 命令无法执行,但 4.X 文档提示支持该语法。根据文档语句生成具体命令:
代码语言:javascript
代码运行次数:0
运行
复制
ALTER SYSTEM SWITCH REPLICA LEADER LS = 1002 SERVER = '10.0.139.175:2882' TENANT = mysql_tenant1;

执行切换后,发现所有表和分区的 LEADER 位于 zone2 的,都切换到了 zone3,说明 zone3 正常,只是由于某种原因无法“承担”表的 LEADER。查看日志流分布的语句为:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT a.TENANT_ID,a.LS_ID,a.SVR_IP,a.SVR_PORT,a.ZONE,a.role,b.TENANT_NAME,b.TENANT_TYPE FROM oceanbase.CDB_OB_LS_LOCATIONS a, oceanbase.DBA_OB_TENANTS b WHERE a.TENANT_ID=b.TENANT_ID;
返回结果
返回结果

返回结果

根据返回结果显示,日志流的 LEADER 也只位于 zone1、zone3。

4日志流

4.1 日志管理

4.1.1 日志流工作原理
  1. OceanBase 使用日志流(LS、Log Stream)在多副本之间同步状态。每个 Tablet(可理解为一个分区、一个分区索引或一个非分区表)都会对应一个确定的日志流,每个日志流对应多个 Tablet,DML 操作写入 Tablet 的数据所产生的 Redo 日志会持久化在日志流中。日志流的多个副本会分布在不同的可用区中,多个副本之间维持共识算法,选择其中一个副本作为主副本(Leader),其他副本为从副本(Follower)。
  2. OceanBase 数据库遵循 WAL(write-ahead logging)原则,在事务提交前将 Redo 日志持久化,并使用 Multi-Paxos 协议在多个副本间同步 Redo 日志,即日志流。同一个日志流具有相同的 LSID。
  3. 对于租户 T1 在机器 S1 的所有 Tablet 产生的日志会写入到同一个日志流 LS1,然后 LS1 在机器 S1 将作为 LEADER ,在机器 S2、S3 作为 FOLLOWER。同时,租户 T1 在机器 S2 也有一个日志流 LS2;租户 T1 在机器 S3 也有一个日志流 LS3。
  4. 只有作为 Leader 的日志流,对应机器的 Tablet 才能提供写服务或强一致性读,其它副本只能被动接受日志。
  5. OceanBase 所有的日志流都对应租户,日志文件存放路径为 <data_dir>/clog/tenant_xxxx(xxxx 表示租户 ID),sys 租户对应则为 <data_dir>/clog/tenant_1;文件以从 0 开始的编号(一直递增,不重复)进行命名;单个日志文件大小为 64MB。该方式与传统数据库的 Redo 存在明显差异。
  6. sys 租户包括一个 LS,LSID 为 1;各 META$xxxx(xxxx 表示租户 ID)租户包括一个 LS,LSID 为 1;各业务租户包含 N + 1 个 LS(N 表示租户中 Zone 的个数),LSID 分别为 1、1001、1002、...,其中 LSID = 1 对应各租户的内部数据库的 Tablet,如 OceanBase、MySQL,1001 或更高的 LSID 在租户的各个 Zone 各有一个,对应所有业务数据库内的 Tablet。
4.1.2 日志大小管理
4.1.2.1 集群空间管理的配置项

log_disk_size

  1. 用于设置 Redo 日志磁盘的大小,即本 OBServer 进程(节点)可以使用的日志盘总空间大小。各个节点可以保持不同 log_disk_size 参数。
  2. 该配置项的值为 0 时,会根据 log_disk_percentage 配置项设置的值分配日志盘空间。
  3. OBServer 节点启动时,会预分配足够多的日志文件。例如:用户配置 log_disk_size = 100G,那么 OBServer 节点第一次启动时,就会预分配 100G 的日志文件作为日志文件池。
  4. 预分配的路径 <data_dir>/clog/log_pool/ 下很多 64MB 的文件。

log_disk_percentage

  1. 用于设置 Redo 日志占用其所在磁盘总空间的百分比。只有 log_disk_size = 0 时,才会根据 log_disk_percentage 配置项设置的值分配日志盘空间;否则 log_disk_percentage 不生效。
  2. log_disk_percentage = 0log_disk_size = 0 同时满足时,系统会根据日志和数据是否共用同一磁盘来自动计算 Redo 日志占用其所在磁盘总空间的百分比:
    • 共用时,Redo 日志占用其所在磁盘总空间的百分比为 30%,即分配磁盘总空间 30% 的日志文件。
    • 独占时,Redo 日志占用其所在磁盘总空间的百分比为 90%,即分配磁盘总空间 90% 的日志文件。
4.1.2.2 租户空间管理
  1. 日志大小通过规格的 log_disk_size 属性指定,最小为 2G(否则规格将创建失败)。当未指定时,log_disk_size 将默认设置为内存的 3 倍大小。
  2. 规格的日志大小包含业务租户和 meta 租户(且相互隔离):其中 meta 租户 = max(log_disk_size * 10%, 512M),剩余的给业务租户。
  3. OBServer 节点上创建租户Unit时,会为Unit预留足够多的日志盘空间,如果本地剩余日志盘空间(日志盘可用空间总大小 — 已分配空间)不满足Unit规格要求,则创建租户 Unit 失败。
  4. 每个租户在分配或扩容时,可以通过视图 oceanbase.GVOB_SERVERS 来查询节点总资源和已经分配的资源。确保所有租户的 log_disk_size满足: sum(log_disk_size) <= GV
4.1.3 日志空间回收
回收条件
  1. 当一个 clog 文件中的所有分区日志对应的数据都已经转储到 SSTable 中时,该 clog 文件就满足了回收条件。
  2. 当租户日志盘使用量超过租户日志盘空间总量乘以 log_disk_utilization_threshold 时,进行日志文件重用。
  3. 当租户日志盘使用量超过租户日志盘空间总量乘以 log_disk_utilization_limit_threshold 时,不再允许日志写入。
回收过程
  1. 检查与标记:OceanBase 系统会定期检查 clog 文件的回收条件。一旦某个 clog 文件满足回收条件,它就会被标记为可回收。
  2. 日志回放与确认:在回收 Clog 文件之前,系统会确保与该文件相关的所有日志都已经成功回放并持久化到数据文件中。这是通过 Paxos 协议在多个副本间同步日志来实现的。
  3. 删除与重用:一旦确认 Clog 文件不再需要,系统就会将其删除以释放存储空间。同时,为了优化存储空间的使用,OceanBase 还允许在日志文件空间不足时重用旧的日志文件。

4.2 检查日志流状态

了解日志流原理及与表/分区的关系后,发现表/分区的 LEADER 分布由日志流的 LEADER 分布决定。再次检查表的分布和日志流分布:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT a.tenant_id,tenant_name,database_name,ls_id,zone,svr_ip,role,count(1)
FROM OCEANBASE.CDB_OB_TABLE_LOCATIONS a join oceanbase.DBA_OB_TENANTS b
on a.tenant_id=b.tenant_id
group by tenant_name,database_name,ls_id,zone,svr_ip,role
order by a.tenant_id,database_name,ls_id;

发现 meta 租户的日志流 LSID = 1 已正常建立完成,业务租户的 LSID = 1 日志流已正常建立完成,LSID = 1001 已正常建立完成,LSID = 1002 只建立了两个副本,LSID = 1003 无副本。

通过 CDB_OB_LS 检查日志流的状态,发现日志状态一直处于 CREATING 中:

代码语言:javascript
代码运行次数:0
运行
复制
select TENANT_ID,LS_ID,STATUS,PRIMARY_ZONE from oceanbase.CDB_OB_LS;

该状态表示日志流一直处于“创建中”。那为何会出现该状态呢!

5错误日志分析

5.1 错误日志知识点

  1. OceanBase 的日志路径下的 log 目录,默认路径在 /home/admin/oceanbase/log
  2. 包含 4 个主日志 observer.log、rootservice.log、election.log 和 trace.log,分别对应 observer 日志、RS 日志、选举日志和全链路追踪日志。
  3. 当主日志达到 256M 时,通过 RENAME 为其归档,命名是在后面加上时间戳,比如 observer.log.20240901123456
  4. 日志格式为:[时间] 日志级别 [所属模块] 函数名(文件:行号) [线程id][线程名][所属租户][trace_id] 日志内容 [(内容相关参数)]。日志从低到高分为:DEBUG、TRACE、INFO、WARN、USER_ERR、ERROR。其中 ERROR 日志比较特殊,会将打日志时所在的堆栈打印出来(需要通过符号表解析)。
  5. trace_ID:OceanBase 数据库内部的 SQL 级别的 ID,格式为 Y0 - 0000000000000000 - 0 - 0,可以根据找到一条 SQL 的执行过程,是排查问题的重要手段。也可以通过 SELECT last_trace_id(); 显示获取 trace_id。
  6. 除了 4 个主日志,还有 observer.log.wf、rootservice.log.wf。该日志包括 WARN 级别或以上的日志。当主日志被归档时,wf 日志也会同时被归档,并保持与主日志相同的时间戳后缀。根据 wf 日志的 trace_id,在主日志找到 SQL 的执行过程;根据时间在主日志找到某一行具体的日志。
  7. 相关参数(略)。

5.2 检查日志

检查 wf 日志,发现频繁产生 ERROR 错误:

代码语言:javascript
代码运行次数:0
运行
复制
[2024-10-29 00:03:56.112302] ERROR issue_dba_error (ob_Log.cpp:1875)[38115][T1060_L0_G0][T1060][YB420A008BAD-000624C0A09C1A91-0-0] [Lt-17][errcode=4388] Unexpect
ed internal error happen, please checkout the internal errcode(errcode=-4264, file="ob_log_service.cpp", Lne_no=b89, info="create_ls failed!!!")

根据 wf 日志的 trace_id 在 observer.log 过滤,然后根据时间戳搜索具体的日志行(此处未展示具体日志内容)。

根据日志,看到 create_ls failed,失败原因是 OB_LOG_OUTOF_DISK_SPACE。进一步发现 PALF(Paxos - base Append - only File System,是 OceanBase 日志同步服务进行打包后的一个框架简称。每个租户的 zone 都有一个 palf,负责对应 zone、租户下的日志的写入和同步服务)模块中返回异常:PalfEnv can not hold more instance,并反馈 log_disk_size 相关参数。

执行以下 SQL 检查数据库的日志使用情况:

代码语言:javascript
代码运行次数:0
运行
复制
select SVR_IP,SVR_PORT,UNIT_ID,TENANT_ID,
ceil(LOG_DISK_SIZE/1024/1024) LOG_DISK_SIZE_M,ceil
(LOG_DISK_IN_USE/1024/1024) LOG_DISK_IN_USE_M,
round(LOG_DISK_IN_USE/LOG_DISK_SIZE*100) LOG_USE_PCT,
ceil(DATA_DISK_IN_USE/1024/1024/1024) DATA_DISK_IN_USE_G,
STATUS  from oceanbase.GV$OB_UNITS 
order by SVR_IP,TENANT_ID;
代码语言:javascript
代码运行次数:0
运行
复制
select SVR_IP,ZONE,
round(LOG_DISK_CAPACITY/1024/1024/1024) LOG_DISK_CAPACITY_G,
round(LOG_DISK_ASSIGNED/1024/1024/1024) LOG_DISK_ASSIGN_G,
round(LOG_DISK_ASSIGNED/LOG_DISK_CAPACITY*100) LOG_USE_PCT
from oceanbase.GV$OB_SERVERS;

根据 OceanBase 日志管理机制和当前使用数据,发现对应的业务租户的使用率偏低,未见异常。

确认租户创建语句:

代码语言:javascript
代码运行次数:0
运行
复制
CREATE RESOURCE UNIT S4_unit_config
MEMORY_SIZE = '1536M',
MAX_CPU = 1, MIN_CPU = 1,
LOG_DISK_SIZE = '2048M',
MAX_IOPS = 10000, MIN_IOPS = 10000, IOPS_WEIGHT=1;

CREATE RESOURCE POOL mq_pool_04 
UNIT='S4_unit_config', 
UNIT_NUM=1, 
ZONE_LIST=('zone1','zone2','zone3'); 

CREATE TENANT IF NOT EXISTS mysql_tenant4 
PRIMARY_ZONE='zone1,zone2,zone3', 
RESOURCE_POOL_LIST=('mq_pool_04')
set OB_TCP_INVITED_NODES='%';

指定了租户的 LOG_DISK_SIZE 为 2GB,结合日志使用情况,OceanBase 对 meta 租户分配了 512MB,业务租户分配了 1536MB。通过官方相关参数规范,满足最小值要求,但创建仍失败。

5.3 针对 LOG_DISK_SIZE 进行租户创建测试

根据以上测试结果,发现只有当 LOG_DISK_SIZE 大小必须大于 2560M 时,所有 LS 才会创建成功,否则会创建失败。

5.4 DEBUG 分析

根据 observer.log 的日志内容,在 palf_env_impl.cpp/palf_env.cpp 添加断点,然后重复创建租户。跟踪发现租户创建过程中存在如下堆栈:

代码语言:javascript
代码运行次数:0
运行
复制
#0  oceanbase::palf::PalfEnvImpl::check_can_create_palf_handle_impl_() const (this=0x7fe7c33fc030) at ./src/logservice/palf/palf_env_impl.cpp:1197
#1  0x00007fe820571e72 in oceanbase::palf::PalfEnvImpl::create_palf_handle_impl_(long, oceanbase::palf::AccessMode const&, oceanbase::palf::PalfBaseInfo const&, oceanbase::palf::LogReplicaType, oceanbase::palf::IPalfHandleImpl*&) (this=0x7fe7c33fc030, palf_id=1001, access_mode=@0x7fe7bb14d2ec: APPEND, palf_base_info=..., replica_type=NORMAL_REPLICA, 
    ipalf_handle_impl=@0x7fe7bb14d0f0: 0x0) at ./src/logservice/palf/palf_env_impl.cpp:416
#2  0x00007fe82056aac1 in oceanbase::palf::PalfEnvImpl::create_palf_handle_impl(long, oceanbase::palf::AccessMode const&, oceanbase::palf::PalfBaseInfo const&, oceanbase::palf::IPalfHandleImpl*&) (this=0x7fe7c33fc030, palf_id=1001, access_mode=@0x7fe7bb14d2ec: APPEND, palf_base_info=..., palf_handle_impl=@0x7fe7bb14d0f0: 0x0) at ./src/logservice/palf/palf_env_impl.cpp:382
#3  0x00007fe82056a91c in oceanbase::palf::PalfEnv::create(long, oceanbase::palf::AccessMode const&, oceanbase::palf::PalfBaseInfo const&, oceanbase::palf::PalfHandle&) (
    this=0x7fe7c33fc030, id=1001, access_mode=@0x7fe7bb14d2ec: APPEND, palf_base_info=..., handle=...) at ./src/logservice/palf/palf_env.cpp:110
#4  0x00007fe81f7fd54e in oceanbase::logservice::ObLogService::create_ls_(oceanbase::share::ObLSID const&, oceanbase::common::ObReplicaType const&, oceanbase::share::ObTenantRole const&, oceanbase::palf::PalfBaseInfo const&, bool, oceanbase::logservice::ObLogHandler&, oceanbase::logservice::ObLogRestoreHandler&) (this=0x7fe7a5404030, id=..., 
    replica_type=@0x7fe7bb14d834: REPLICA_TYPE_FULL, tenant_role=..., palf_base_info=..., allow_log_sync=true, log_handler=..., restore_handler=...)
    at ./src/logservice/ob_log_service.cpp:665
#5  0x00007fe81f7fcdcc in oceanbase::logservice::ObLogService::create_ls(oceanbase::share::ObLSID const&, oceanbase::common::ObReplicaType const&, oceanbase::share::ObTenantRole const&, oceanbase::palf::PalfBaseInfo const&, bool, oceanbase::logservice::ObLogHandler&, oceanbase::logservice::ObLogRestoreHandler&) (this=0x7fe7a5404030, id=..., 
    replica_type=@0x7fe7bb14d834: REPLICA_TYPE_FULL, tenant_role=..., palf_base_info=..., allow_log_sync=true, log_handler=..., restore_handler=...)
    at ./src/logservice/ob_log_service.cpp:343
#6  0x00007fe828b07498 in oceanbase::storage::ObLS::create_ls(oceanbase::share::ObTenantRole, oceanbase::palf::PalfBaseInfo const&, oceanbase::common::ObReplicaType const&, bool) (
    this=0x7fe7996cc150, tenant_role=..., palf_base_info=..., replica_type=@0x7fe7bb14d834: REPLICA_TYPE_FULL, allow_log_sync=true) at ./src/storage/ls/ob_ls.cpp:405
#7  0x00007fe828c79ebf in oceanbase::storage::ObLSService::create_ls(oceanbase::obrpc::ObCreateLSArg const&) (this=0x7fe7909ce030, arg=...)
    at ./src/storage/tx_storage/ob_ls_service.cpp:508
#8  0x00007fe8232d8c52 in oceanbase::observer::ObRpcCreateLSP::process() (this=0x7fe7bb15a700) at ./src/observer/ob_rpc_processor_simple.cpp:1521
#9  0x00007fe81f601db0 in oceanbase::obrpc::ObRpcProcessorBase::run() (this=0x7fe7bb15a700) at ./deps/oblib/src/rpc/obrpc/ob_rpc_processor_base.cpp:89
#10 0x00007fe822b07e66 in oceanbase::omt::ObWorkerProcessor::process_one(oceanbase::rpc::ObRequest&) (this=0x7fe7775931a8, req=...) at ./src/observer/omt/ob_worker_processor.cpp:88
#11 0x00007fe81f2959d3 in oceanbase::omt::ObWorkerProcessor::process(oceanbase::rpc::ObRequest&) (this=0x7fe7775931a8, req=...) at ./src/observer/omt/ob_worker_processor.cpp:157
#12 0x00007fe822b06d01 in oceanbase::omt::ObThWorker::process_request(oceanbase::rpc::ObRequest&) (this=0x7fe7775930e0, req=...) at ./src/observer/omt/ob_th_worker.cpp:248
#13 0x00007fe81f294a8f in oceanbase::omt::ObThWorker::worker(long&, long&, int&) (this=0x7fe7775930e0, tenant_id=@0x7fe7bb14ec98: 1046, 
    req_recv_timestamp=@0x7fe7bb14ec90: 1729995314847463, worker_level=@0x7fe7bb14ec8c: 0) at ./src/observer/omt/ob_th_worker.cpp:387
#14 0x00007fe822b072bc in oceanbase::omt::ObThWorker::run(long) (this=0x7fe7775930e0, idx=0) at ./src/observer/omt/ob_th_worker.cpp:424
#15 0x00007fe82ea0c271 in oceanbase::lib::Thread::run() (this=0x7fe777593310) at ./deps/oblib/src/lib/thread/thread.cpp:164
#16 0x00007fe82ea0bdae in oceanbase::lib::Thread::__th_start(void*) (arg=0x7fe777593310) at ./deps/oblib/src/lib/thread/thread.cpp:322
#17 0x00007fe819435dc5 in start_thread () from /lib64/libpthread.so.0
#18 0x00007fe81916473d in clone () from /lib64/libc.so.6

在执行 PALF 处理接口创建过程中,需要执行如下检查:

代码语言:javascript
代码运行次数:0
运行
复制
bool PalfEnvImpl::check_can_create_palf_handle_impl_() const{
    bool bool_ret = true;
    // 统计Palf处理接口的个数。例如当租户的PRIMARY_ZONE三个zone时,返回3.只有一个zone时,返回1
    int64_t count = palf_handle_impl_map_.count();
    // 获取磁盘的参数,包括总大小,回收阈值,限制写入阈值等属性。其中log_disk_usage_limit_size_即为当前该租户创建指定的log_disk_size(2048M) - 租户的日志组大小(512M) = 1536M.
    const PalfDiskOptions disk_opts = disk_options_wrapper_.get_disk_opts_for_recycling_blocks();
    // MIN_DISK_SIZE_PER_PALF_INSTANCE源码定义为512M
    // 计算 (3+1)*512=2048,2048 <= 1536不成立,因此将返回bool_ret为false
    bool_ret = (count + 1) * MIN_DISK_SIZE_PER_PALF_INSTANCE <= disk_opts.log_disk_usage_limit_size_;
    return bool_ret;
}

结合日志流相关原理和实现代码:

当需要创建一个包含 3 个 zone 的租户时,所需的日志具体数量如下:

因此,当租户指定的 PRIMARY_ZONE 为 3 个 zone 时,租户在创建时,需要为业务租户创建 4 个日志流,所需的最小日志流大小:

(3+1) × 每个 PALF 的最小日志磁盘空间 = 1 × 512MB = 2048M

由于当前业务租户总的日志大小为总的规格大小 - meta 租户的日志大小为 1536M,小于所需的 2048M,无法满足日志需求检查不通过,LSID=1003 无法创建成功。

6故障总结与建议

综合以上分析过程,导致本次单机改三副本操作完成后,表的副本无法均分到三个 zone 的根本原因为:租户创建过程中,规格的 log_disk_size 为 2048M,去除 meta 租户的日志大小,业务租户剩余大小为 1536M。租户的 PRIMARY_ZONE 包含 3 个 zone,OceanBase 内部在创建日志流时,需要检查业务租户的日志空间是否满足总的日志大小大于 4×512M,由于无法满足,导致 LSID=1003 的日志流无法创建成功。因此对应的 zone 无法创建表的主副本。

建议

增加规格的 log_disk_size 的大小。如日志空间充足,建议采用默认方式,不指定 log_disk_size 的大小。默认分配为内存的三倍。

如日志空间有限,必须满足 >= 租户的 (PRIMARY_ZONE 个数+2)+512M

本文关键字:#OceanBase# #单机版# #日志# #扩容#

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-02-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 爱可生开源社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1租户扩容
  • 2表的副本管理
  • 3表副本分布异常分析
  • 4日志流
    • 4.1 日志管理
      • 4.1.1 日志流工作原理
      • 4.1.2 日志大小管理
      • 4.1.3 日志空间回收
    • 4.2 检查日志流状态
  • 5错误日志分析
    • 5.1 错误日志知识点
    • 5.2 检查日志
    • 5.3 针对 LOG_DISK_SIZE 进行租户创建测试
    • 5.4 DEBUG 分析
  • 6故障总结与建议
    • 建议
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档