两年前经手过一套还在跑 2.2 的集群第一天上手就栽了个跟头按早前版本的经验写了参数system_memory没动结果 observer 进程起来不到十秒就退出日志里只有一句含糊的内存越界提示。那天下午我盯着日志翻了两个小时才反应过来这个版本对内存划分的校验比之前严格得多。这件事让我意识到一件事——OceanBase 2.2这个版本很多人只在发布会 PPT 上见过它的特性列表真正落到部署和调参上坑比想象中密集。这篇东西就是把这套经验摊开讲2.2 到底改了哪些真正影响架构决策的东西部署一台三副本集群时哪些前置条件不满足就必然翻车以及那些文档里一句话带过、实际要折腾半天才搞明白的参数关系。适合手上有一套存量 2.2 集群要维护的人也适合打算用它替掉分库分表中间件、想先摸清楚底细的人。文中提到的资料包和那份发布会 PPT我会在第一节里说清楚怎么用才不浪费。1. 2.2 这个版本到底卡在一个什么位置上1.1 为什么存量集群里 2.2 的占比一直不低分布式数据库的版本迭代有个特点新版本发布频率高但真正被大规模铺到生产上的往往是那么一两个够用且生态齐的版本。2.2 就属于这种。它往前承接了早期版本在分布式事务和 Paxos 多副本上的积累往后又给后面的版本留出了架构调整空间。很多团队在选型窗口期落地选的就是它。实际维护下来2.2 给人的感觉是半成品感最少的一代。MySQL 协议兼容度够用常见的 ORM 框架、连接池、运维脚本基本不用改多租户模型已经成型一个集群切多个业务库不再是纸面功能分区表和全局索引也在这一代补齐了这意味着原来压在上层的分库分表中间件有了真正被撤掉的可能。当然这都是从能干活的角度说的性能边界和运维复杂度是另一回事后面几节会具体拆。我见过不少团队的做法是新业务直接上更新的版本老业务就留在 2.2 不动因为迁移成本和收益不成正比。这就导致一个现象——你接手的环境里2.2 集群的数量可能比你想的多而网上能找到的、贴着 2.2 讲的部署细节反而不如新版本多。这也是我想把这块写细的原因。1.2 特性清单里真正影响架构决策的就那么几条官方给 2.2 列的特性表很长但站在架构选型的位置上看能改变方案的其实只有四类其余大多属于有了更好、没有也能活的范畴。第一类是分区能力的补全尤其是二级分区。它决定了你的大表能不能在库内拆分到位而不是靠外部中间件做路由。第二类是全局索引它直接决定了带非分区键的查询能不能走索引这是很多方案能不能落地的分水岭。第三类是多租户资源隔离Unit、Pool、Tenant 这一套模型决定了你能不能用一个集群服务多个业务线而不互相拖垮。第四类是副本类型的多样化日志副本的引入让低成本容灾从概念变成了可以算账的方案。其余特性像向量化执行、并行执行、执行计划缓存这些属于性能层面的优化你感知得到但不会因此改变表结构设计备份恢复链路的完善属于运维层面重要但不影响前期的架构判断。我在做技术评审时一般只让人重点看前四类后面的当作加分项。1.3 那份 PPT 的正确用法别当宣传材料翻资料包里那份发布会 PPT我见过太多人翻两页就关掉了因为它看起来全是架构图和支持 XXX的标语。但换个用法它的价值其实不低。最实用的是那张整体架构图。内部做方案评审、给不熟悉这块的同事做科普时直接拿它改字比你自己画一张准确得多——里面把 OBServer、OBProxy、RootService 的分层关系画得很清楚你把 IP 和 zone 换成自己的拓扑就行。其次是版本特性对比的那几页做技术选型时如果需要在几个方案之间做取舍这几页的条目可以直接作为对比维度省得自己列清单。第三是部署拓扑图三副本怎么摆、OBProxy 放在哪一层、是否需要独立的 OCP 节点图上一目了然照着它画你的实际部署图基本不会漏。真正需要你自己补的是参数部分。PPT 上不会告诉你system_memory默认值有多大、小规格机器必须先改哪几个参数才能 bootstrap 成功这些只能靠实测或者踩坑积累。资料包里的那些图当成骨架用参数和流程当成血肉自己填这样组合起来才是一份能拿去开会的东西。2. 分区表与全局索引能不能真把中间件撤掉2.1 二级分区模板解决的是运维成本问题单层分区在业务早期够用但一旦表大到需要按时间和业务维度同时切分单层分区就尴尬了按时间切所有业务线挤在一个分区里按业务切时间维度的清理又做不了。二级分区就是为这个场景准备的。2.2 里的二级分区有两种写法差别很大。模板化二级分区是先定义一级分区的规则然后挂一个二级分区模板后续新增一级分区时自动按模板生成对应的二级分区。非模板化二级分区则是每个一级分区下面单独定义二级分区灵活性更高但维护成本也更高。我给的建议通常是如果二级分区的规则在所有一级分区下完全一致绝大多数按时间 按业务线切的场景都是这样一律用模板化。理由是运维脚本的复杂度差一个量级——模板化分区加一级分区只要一条ADD PARTITION非模板化的要针对每个一级分区单独写。我见过一个环境用了非模板化分区结果自动化扩容脚本写了一千多行每次加分区还要校验一遍纯粹是给自己找麻烦。-- 模板化二级分区示例 CREATE TABLE t_order ( order_id BIGINT NOT NULL, tenant_id BIGINT NOT NULL, create_time DATETIME NOT NULL, amount DECIMAL(12,2), PRIMARY KEY (order_id, create_time) ) PARTITION BY RANGE COLUMNS(create_time) SUBPARTITION BY HASH(tenant_id) SUBPARTITIONS 16 ( PARTITION p202401 VALUES LESS THAN (2024-02-01), PARTITION p202402 VALUES LESS THAN (2024-03-01) );这段建表语句里有个容易被忽略的点主键必须包含分区键。很多人从单机 MySQL 迁过来主键只写order_id建表直接报错。这不是限制是分布式环境下的必然要求——分区键不在主键里唯一性就没法在分区层面保证。改主键的时候要顺手检查一下业务代码里有没有依赖单列主键的地方比如某些 ORM 的自增主键映射这块改起来比建表本身麻烦。2.2 全局索引的写放大账要提前算全局索引是 2.2 让很多人兴奋的功能因为它意味着非分区键的等值查询也能走索引了。以前的做法要么全分区扫要么建一张冗余表自己维护现在一条CREATE INDEX ... GLOBAL就解决。CREATE INDEX idx_order_no ON t_order(order_no) GLOBAL;但写放大的账必须提前算清楚。本地索引的维护只发生在数据所在的那个分区成本可控全局索引本质上是一张独立的分区表每次基表写入都要额外维护索引分区而且索引分区的分布和基表分区不一定对齐跨机的分布式事务概率会明显上升。我的经验判断标准是这样的如果这张表的写入 QPS 在几千以上且全局索引的列更新频繁先做一次压测再决定。曾经有个场景给一张日增千万行的表加了两个全局索引写入吞吐掉了将近四成最后砍掉一个、另一个改成异步补偿的冗余表才收场。反过来如果是读多写少的配置类、维表类数据全局索引几乎没有任何犹豫的必要直接建。还有一个坑全局索引建完之后EXPLAIN里是否真的走了索引跟查询写法强相关。建了索引不等于查询会用这一点下一节细说。2.3 分区裁剪失效的三种典型写法分区表建好之后最常见的抱怨是为什么还是全表扫。我排查过的案例里绝大多数不是优化器的问题是 SQL 写法让裁剪没法生效。三种高频情况第一种分区键上套了函数。WHERE DATE(create_time) 2024-01-15这种写法优化器没法从函数结果反推分区范围只能全扫。改成WHERE create_time 2024-01-15 AND create_time 2024-01-16就正常了。这个改法看起来笨但它是唯一可靠的。第二种分区键参与运算或隐式转换。字段是DATETIME条件里传了字符串还好传了数字或者用了UNIX_TIMESTAMP比较裁剪直接失效。这类问题在 MyBatis 的动态 SQL 里特别常见因为拼接的时候类型丢了。第三种参数化查询里的绑定变量。某些情况下绑定变量会让优化器在生成计划时拿不到具体的分区键值尤其是范围查询。这个要看具体小版本的行为我的做法是先把 SQL 里的变量换成常量跑一遍EXPLAIN确认能裁剪再判断是不是绑定变量导致的。排查的时候我固定用这套流程先EXPLAIN看partitions列有没有列出具体分区再SHOW WARNINGS看有没有隐式转换提示最后把 SQL 拆到最简形式逐个条件加回去。三步下来基本能定位。3. 多租户模型Unit、Pool、Tenant 三层怎么算3.1 资源单元规格与内存的换算关系多租户这套模型第一次接触会觉得绕其实就三层资源单元Unit是规格模板定义 CPU、内存、IOPS、连接数上限资源池Pool是把若干 Unit 分布到各个 Zone 上的容器租户Tenant是使用资源池的业务实例。一个人租房子Unit 是房型图Pool 是具体某几套房Tenant 是签合同的人。创建语句大致长这样CREATE RESOURCE UNIT unit_s1 MAX_CPU 8, MIN_CPU 8, MEMORY_SIZE 16G, MAX_IOPS 10000, MIN_IOPS 10000, MAX_SESSION_NUM 10000; CREATE RESOURCE POOL pool_biz1 UNIT unit_s1, UNIT_NUM 1, ZONE_LIST (zone1,zone2,zone3); CREATE TENANT tenant_biz1 RESOURCE_POOL_LIST (pool_biz1), PRIMARY_ZONE zone1;zone2,zone3, CHARSET utf8mb4, OB_COMPATIBILITY_MODE mysql;这里最需要算清楚的是内存。MEMORY_SIZE是一个 Unit 的规格Pool 里UNIT_NUM 1且三个 Zone意味着这个租户在三个 Zone 上各有一份 16G 的副本物理上占用 3 × 16G。但租户可用的逻辑内存是 16G不是 48G因为三份是副本关系。这一点很多人第一次算的时候会搞混以为三副本能当三倍内存用。单机可分配的总量怎么算大致是memory_limit - system_memory再留一点余量给 observer 内部使用。我的经验是把所有租户的 Unit 内存总和控制在(memory_limit - system_memory) × 0.8以内剩下的 20% 是给合并、缓存、突发的缓冲。卡得太死合并期间容易触发内存不足的保护行为。3.2 副本类型的选择全能、日志、只读2.2 的副本类型不止一种。全能副本是常规的三副本或者五副本配置既能选主也能提供读写日志副本只同步 clog 不存基线数据成本低主要用来凑够 Paxos 的多数派只读副本可以承接读流量但不能参与选举。日志副本的用法是很多方案里的省钱关键。比如五副本的配置如果全用全能副本存储成本是五份换成三个全能副本加两个日志副本多数派照样满足存储成本降下来一大截代价是容灾切换时的可选范围变窄——日志副本没法直接升主打服务得先转成全能副本。这个转换不是瞬间完成的需要时间。只读副本适合读多写少且读流量集中的场景比如报表类查询。但要注意只读副本的数据一致性是最终一致的延迟通常在秒级以内做实时性要求高的查询会读到旧数据。我在一个统计场景里用过业务方一开始不理解为什么数字和主库对不上后来在应用层加了一个数据延迟不超过 5 秒的提示才解决。租户创建的时候用LOCALITY指定副本分布写法大致是LOCALITYFzone1,Fzone2,Fzone3,Lzone4这种形式F 表示全能副本L 表示日志副本。这个字符串要仔细核对写错了创建出来的租户副本分布不符合预期后面调整很麻烦。3.3 租户建完之后必须确认的五件事租户创建成功不代表能直接用。我有一份固定检查清单每次建完租户都跑一遍第一PRIMARY_ZONE是否符合预期。默认值可能把所有主副本都放在第一个 Zone导致读写压力集中。用SELECT * FROM oceanbase.DBA_OB_TENANTS;看实际配置。第二连接串里的租户名格式对不对。OceanBase 的连接用户格式是用户名租户名系统租户是rootsys业务租户是roottenant_biz1。连接串写错是新手最常见的错误报错信息还不直观。第三字符集和排序规则。建租户时指定的CHARSET是租户级默认值建库建表时如果不显式指定会继承。从 MySQL 迁移过来的库排序规则经常对不上导致ORDER BY结果和原库不一致。第四租户的内存水位。用SELECT * FROM oceanbase.__all_virtual_tenant_memstore_info;观察 memstore 使用情况如果一上来就接近上限说明 Unit 规格给小了。第五系统变量差异。sql_mode、autocommit、tx_isolation这些在租户级别可以覆盖从 MySQL 迁移时把源库的配置导出来对一遍能避免一大批次莫名其妙的行为差异。4. 部署前的机器核对比安装步骤更容易翻车4.1 从内存参数反推机器规格部署文档通常写的是建议 XX 核 XX G但实际配置机器的时候得从参数反推。这里的关键是memory_limit和system_memory的关系。memory_limit是 observer 能使用的内存上限默认可能配的是按百分比取小机器上建议显式写死。system_memory是预留给系统内部使用的部分这个参数在很多版本里默认值偏大接近 30G 这个量级如果你的机器只有 32G 内存不改它基本起不来。我一般按这个顺序倒推先确定机器物理内存比如 64Gmemory_limit设成 48G 左右留 16G 给操作系统和其他进程system_memory设成 8G那么可用于租户的内存就是 40G按 0.8 系数算实际分配给租户的总量控制在 32G 以内。CPU 方面cpu_count不写会自动探测但如果机器上还跑着别的东西建议显式指定避免 observer 抢满所有核。IOPS 参数在 SSD 环境下可以设得高一些机械盘上设太高反而会因为实际达不到而拖慢判断。有一个参数值得单独拎出来说__min_full_resource_pool_memory。它限制了一个 Unit 的最小内存默认值是个比较大的数字5G 量级。如果你要给测试环境建一个 2G 的小租户会直接报错提示资源单元内存太小。解决办法是把这个参数调小然后重启 observer 生效。这是我在测试环境上浪费过半小时的坑——报错信息只说了资源不足没说是这个参数卡住的。-- 需要在 sys 租户执行调整后重启 observer ALTER SYSTEM SET __min_full_resource_pool_memory 1073741824;4.2 操作系统层面必须做完的几件事这部分看起来琐碎但少做一件后面就要回来补。用户与权限。用一个专用的普通用户跑 observer不要用 root。创建用户后配置limits.conf重点是nofile和nproc设成 655360 这个量级。nofile不够的表现是运行一段时间后报打开文件过多而且往往是在压力上来之后才暴露排查时容易误判成别的毛病。useradd -U admin -s /bin/bash -m /home/admin cat /etc/security/limits.conf EOF admin soft nofile 655360 admin hard nofile 655360 admin soft nproc 655360 admin hard nproc 655360 admin soft stack unlimited admin hard stack unlimited EOF透明大页。必须关掉。不关的话内存分配延迟会抖动合并期间尤其明显。写入/sys/kernel/mm/transparent_hugepage/enabled和defrag两个文件值设为never并且要写进开机脚本否则重启后失效。时钟同步。这一条是硬性要求不是建议。多副本靠 Paxos 选主和同步日志节点间时钟偏差过大可能导致选主异常甚至集群分裂。用 chrony 或者 ntp 都行关键是所有节点指向同一个时间源并且用chronyc sources -v或者ntpq -p确认同步状态是正常的。我见过一个环境因为一台机器的时钟快了十几秒bootstrap 反复失败日志里完全没有时钟相关的提示最后靠对比三台机器的date才发现。防火墙与 SELinux。测试环境图省事关掉最省心生产环境按需放行端口。需要放行的至少包括 SQL 端口默认 2881、RPC 端口默认 2882如果部署了 OBProxy 还要放行它的端口常用 2883。4.3 磁盘与目录的规划逻辑OceanBase 的磁盘规划有个基本原则数据和日志分离最好落在不同的物理盘上。数据目录放基线数据和转储文件日志目录放 clog两者的 IO 特征完全不同——数据盘是顺序大 IO日志盘是小 IO 高并发。混在一块盘上合并期间日志写入可能被拖慢进而影响事务提交。目录结构大致是这样/home/admin/oceanbase放软件和运行日志/data/1放数据文件/data/log1放 clog。三个目录最好分属不同的挂载点。文件系统用 ext4 或者 xfs 都行我用 ext4 多一些注意挂载参数里加上noatime减少不必要的元数据写入。磁盘容量怎么估数据目录按业务数据量的压缩后大小乘以 1.5 到 2 倍预留要留转储和合并的空间日志目录按数据目录的 3 到 5 倍预留。这个比例不是死的跟写入量强相关——写入越频繁clog 增长越快。如果日志盘用满了会怎样observer 会停止写入业务表现为挂起比报错更难排查。所以clog_disk_utilization_threshold这个参数要关注默认在 80% 左右开始告警超过上限就暂停服务了。预读参数可以在压测阶段按实际表现调我一般不在一开始就动它先跑通再优化。磁盘调度器如果在虚拟化环境里改成noop或者none通常比默认的更合适但这也得看底层存储类型。5. 拉起集群一键部署和手工 Bootstrap 两条路5.1 OBD 配置文件逐项说明OBD 是这一代主推的部署工具适合快速拉起标准拓扑。核心是一个 YAML 配置文件我挑关键项讲user: username: admin password: your_password port: 22 oceanbase-ce: servers: - name: server1 ip: 10.0.0.11 - name: server2 ip: 10.0.0.12 - name: server3 ip: 10.0.0.13 global: devname: eth0 home_path: /home/admin/oceanbase data_dir: /data/1 redo_dir: /data/log1 cluster_id: 1 appname: obcluster memory_limit: 48G system_memory: 8G datafile_size: 200G root_password: your_root_pwd server1: zone: zone1 server2: zone: zone2 server3: zone: zone3几个容易写错的地方devname要填实际的网卡名填错了 observer 绑不上地址zone是配在每个 server 下面的不是配在 global 里的写到 global 里会不生效datafile_size是单副本的数据文件初始大小不是总量三副本就是三倍cluster_id和appname必须全集群一致不一致会导致节点认不到彼此。部署和启动obd cluster deploy obcluster -c ob.yaml obd cluster start obcluster obd cluster display obclusterdeploy阶段做的是分发软件包、渲染配置、初始化目录start阶段才是真正拉起 observer 并 bootstrap。如果start卡住先看obd cluster display的输出再去各节点的 observer 日志里找关键字通常问题出在内存参数或者时钟同步上。5.2 手工 Bootstrap 的完整流程不理解一键部署背后做了什么出了问题就只能干瞪眼。手工流程走一遍心里就有底了。第一步在每个节点上启动 observer 进程但不 bootstrap。启动命令大致长这样cd /home/admin/oceanbase ./bin/observer -i eth0 -p 2881 -P 2882 -z zone1 \ -d /data/1 -r 10.0.0.11:2882 \ -o memory_limit48G,system_memory8G,datafile_size200G,cluster_id1,appnameobcluster-r参数填的是 rootservice 的候选列表第一次启动时填自己和另外两个节点的地址。这时候进程是起来的但还没有集群元数据。第二步在任意一个节点上执行 bootstrap只执行一次ALTER SYSTEM BOOTSTRAP ZONE zone1 SERVER 10.0.0.11:2882, ZONE zone2 SERVER 10.0.0.12:2882, ZONE zone3 SERVER 10.0.0.13:2882;执行完这条语句集群开始选主、初始化系统租户。这一步失败的原因八成是节点间网络不通或者时钟不同步。执行完之后用SELECT * FROM oceanbase.__all_server;确认三个节点的状态都是active。第三步建资源单元、资源池、业务租户就是第 3 节里那三条语句。系统租户sys是 bootstrap 时自动建的业务租户要自己建。第四步验证主副本分布。用SELECT svr_ip, count(*) FROM oceanbase.__all_virtual_leader GROUP BY svr_ip;看主副本是不是均匀分布在三个节点上。如果全集中在一个节点检查PRIMARY_ZONE的配置。手工流程跑一遍大概二十分钟但这一遍跑完后面遇到任何异常你都知道该去哪一层找原因这个价值远超过省下来的那点时间。5.3 OBProxy 接入与连接串写法业务一般不直连 observer中间加一层 OBProxy 做路由和连接管理。部署 OBProxy 可以走 OBD 的obproxy-ce模块也可以手工解压启动。关键配置是它要能拿到集群的 server 列表通常指向 rootservice 地址。连接串写法是个高频出错点mysql -h 10.0.0.11 -P 2883 -u roottenant_biz1 -p -c -A-u后面的格式是用户名租户名这是必须的不写租户名会被当成系统租户处理然后提示密码错误——这个报错信息非常容易误导人让你以为是密码问题。-c的作用是保留 SQL 注释如果你用 hint 控制执行计划不加这个参数 hint 会被客户端剥掉然后你会疑惑为什么 hint 不生效。-A关掉自动补全能加快连接速度在表多的时候感知明显。5.4 上线前的验证清单集群起来了别急着交出去。我固定跑这几项检查项命令期望结果节点状态SELECT svr_ip, status FROM oceanbase.__all_server;全部 active主副本分布SELECT svr_ip, count(*) FROM oceanbase.__all_virtual_leader GROUP BY svr_ip;各节点数量接近租户状态SELECT tenant_name, status FROM oceanbase.DBA_OB_TENANTS;NORMAL内存使用SELECT * FROM oceanbase.__all_virtual_tenant_memstore_info;远低于上限建表读写建库建表、插入、查询、更新全部正常故障切换停掉一个节点的 observer业务连接不中断主副本自动迁移故障切换那一项最容易被跳过但它恰恰是最该测的。测试方法很简单在业务持续写入的情况下直接把一个节点的 observer 进程 kill 掉观察业务侧有没有报错、多久恢复。正常情况下 OBProxy 会自动把请求路由到新的主副本业务感知到的是一次短暂的重连。如果业务直接挂了说明 OBProxy 的配置或者连接池的重试逻辑有问题这个必须在上线前解决。6. 跑起来之后合并、参数基线与真实报错6.1 合并机制与合并失败的排查链路合并major freeze是 OceanBase 存储引擎的核心动作把内存里的增量数据和磁盘上的基线数据合并成新的基线。2.2 这一代引入了轮转合并的思路可以按 Zone 轮流进行减少对业务的整体冲击。合并由 RootService 定时调度默认在凌晨某个时间点触发。手工触发用ALTER SYSTEM MAJOR FREEZE;。查看状态用SELECT * FROM oceanbase.__all_zone WHERE name IN (merge_status,frozen_time);不同小版本的视图名可能有差异DBA_OB_MAJOR_COMPACTION这个视图在较新的版本里更通用。合并失败是运维里最头疼的问题之一因为它通常是半失败——部分分区合完了部分卡住了集群带着不一致的状态继续跑。排查顺序我一般这样走先看merge_status是MERGING还是TIMEOUT。如果是MERGING长时间不动大概率是资源不足或者有超大分区如果是TIMEOUT说明超时了但还在后台跑。再看SELECT * FROM oceanbase.__all_virtual_merge_info;找出卡住的分区。如果是某一个大表的分区基本就是单分区数据量过大合并时间超过了阈值。然后查磁盘。合并过程会写大量临时文件磁盘空间不足会导致合并中断。clog_disk_utilization_threshold到了阈值会停止写入合并自然也进行不下去。最后查内存。合并需要额外的内存做排序和归并如果租户的 memstore 已经吃满合并没有内存可用会一直卡着。这种情况下临时调大 Unit 的内存或者清理一些历史数据合并就能推过去。预防的办法比排查更重要控制单分区的大小我一般建议单分区不超过 50G给合并留足内存余量监控磁盘水位。这三条做到了合并失败的概率会低很多。6.2 参数基线我常用的一套起始值参数没有万能值但有一套相对安全的起始点比默认值更贴近实际场景。下面这张表是我在小规模生产环境上常用的具体还要按压测结果调。参数默认倾向我的起始值理由memory_limit按百分比取显式写死物理内存的 70%~75%避免自动探测把系统内存吃光system_memory偏大8G 或物理内存的 15%小机器不改必失败datafile_size按百分比显式指定留 30% 余量避免转储时空间不足clog_disk_utilization_threshold8070提前告警留出清理时间enable_syslog_recycle关闭开启系统日志不清理迟早吃满盘max_syslog_file_count较小按保留天数算配合上一条使用__min_full_resource_pool_memory5G 量级1G测试环境建小租户必需enable_syslog_recycle这一条值得单独说。observer 的系统日志增长很快不开自动回收几个月就能把软件目录所在的分区写满。而软件目录写满之后observer 直接崩业务全断。这个坑我在一个跑了半年的环境上遇到过凌晨告警爬起来发现是日志盘满了清理完才恢复。从那以后我部署完第一件事就是把这个参数打开。6.3 三个让我印象深刻的坑第一个是内存参数的联动。改memory_limit的时候如果不同时看system_memory很容易出现改了反而起不来的情况。因为system_memory的默认值在某些版本里是个固定数字你把memory_limit调小了但没动它系统内存预留超过总上限直接启动失败。正确做法是两个一起改改完先在一个节点上试启动。第二个是租户内存分配超过物理能力。创建租户的时候MEMORY_SIZE填多少是没校验的只要不超过单机可分配量就能建成功。但如果你的 Pool 里UNIT_NUM大于 1一个 Zone 上会有多个 Unit累加起来可能超过单机内存。表现是集群能跑但一上压力就内存不足。建租户之前算一遍UNIT_NUM × MEMORY_SIZE是不是小于单机可分配量。第三个是时钟漂移的隐性影响。前面提过一次这里说得更具体那台机器不是完全没同步是同步精度差偏差在几秒到十几秒之间波动。这种偏差不会导致明显的功能异常但会让合并时间戳对不上表现为某些分区的frozen_time出现奇怪的值合并调度混乱。换掉时间源之后一切正常。所以时钟检查不能只看有没有配同步要看同步的偏差值。7. 一点个人体会这套东西维护下来最大的感受是分布式数据库的部署和调参难点从来不在那些写得很清楚的步骤上而在参数之间的耦合关系上。单看任何一个参数都觉得合理组合起来就起不来。我现在的习惯是每接手一个新环境先把这几个核心参数的实际值导出来列在一张表上对着物理资源算一遍比看任何文档都管用。资料包里那份 PPT 的架构图我一般会打印一份贴在工位上出问题的时候拿笔在上面标一圈往往标到一半思路就清楚了——因为在标的过程中你会被迫想清楚每一层到底发生了什么。
阅读完成 · 觉得有帮助?