【资深 DBA 进阶培训】第四期 学习笔记 —— OceanBase PoC 与业务上线提效指南 (2025.10.21 更新)

课后练习挑战

课程回放直达

作者:洪波,开源业务部 - 技术专家

基础环境检查事项

基础环境检查事项包括版本选择、安装检查、部署完成后检查、安装过程中的注意事项等。

安装部署前检查

版本选择

OceanBase 官网提供了多个版本,每个不同版本的数据库在功能及特性方面的差异可能会很大,在安装部署前,我们需要了解一下对应的版本号规则及发布计划。

版本号说明

示例:V4.2.1_CE、V4.2.1_CE_BP10、V4.2.1_CE_BP10_HF1

版本规则: VA.B.C_CE[_BETA][_BPX][_HFY]

规则说明:

A.B.C:保留三位版本号

  • A 表示主要的大版本,一般会有架构升级发布。
  • B 表示计划迭代版本,含有重要功能或超大特性更新和提升。
  • C 表示发布更新版本,对已知问题进行修复,一般特性变更。

BP:表示是第 X 个 Bugfix 版本。

HF:表示是第 X 个 Bugfix 版本的第 Y 个 Hotfix。

版本发布计划

BP:正常每个月发布一次,用于修复一些重大的 Bug, 引入一些小功能特性。

HF:由于 BP 版本每个月发布一次,如果在此期间发生重大 Bug,就通过 HF 修复。

针对 AP 和 TP 业务,推荐两个版本

  • 4.3.5:AP 业务, 或对性能要求高的 HTAP,以及有向量检索、自动分区分裂等需求。
  • 4.2.5: TP 业务, 或对稳定性要求高的 HTAP。

版本选择 LTS 版本的最新 BP / HF 即可,目前 V3.1.x 版本已于2024.6.30日起不再维护,建议尽快升级到 4.x 版本.

操作系统检查

操作系统版本

操作系统内核版本检查:uname -r

  • 不推荐使用 3.10 版本内核。
  • 推荐内核版本使用 4.19 版本及以上。
  • 如果使用 Cgroup 功能,Linux 内核版本必须在 5.10 及以上。
  • Linux 内核 5.10 及以上的操作系统,推荐使用 el8 RPM 包。
  • Linux 内核低于 5.10 的操作系统,推荐使用 el7 RPM 包。
  • 关闭透明大页。

环境检查

基础环境检查

  • 检查机器 CPU 核数及型号:lscpu

  • 需要关注几点:

    • CPU 架构,x86 还是 Arm,选择对应的安装包。
    • 指令集,需要确认是否支持 AVX 指令集,当前版本机器不支持 AVX 指令集,无法安装集群(后续会在 V4.2.5_CE_BP6、V4.3.5_CE_BP4,V4.4.1_CE 版本不再要求 AVX 指令集)。
  • 内存检查:free –m

    • 检查机器剩余内存空间是否足够。

    • 若缓存过多,则手动清理缓存。

      • 缓存清理

        • sudo sysctl -w vm.drop_caches=3
        • sudo echo 3 > /proc/sys/vm/drop_caches
案例 – 不支持 AVX 指令集导致集群故障

现象

  • 用户集群突然无法连接。
  • 查看数据库进程,进程已经不在。
  • 查看 observer.log,发现 CRASH ERROR!!!。

问题原因

  • 查看 CPU 指令集,发现不支持 AVX 指令集。
  • 目前不支持 AVX 指令集,会导致集群故障。
  • 当前新的安装工具,在安装时会直接拦截不支持 AVX 指令集的安装。

解决方案

更换支持 AVX 指令集机器。

时钟偏差检查

  • 时钟源配置和时区配置(必须)。
  • clockdiff 命令检查,时钟偏差不大于 100ms ,生产环境不大于 5ms。(官方要求2s,但是建议越小越好)

OCP 接管主机时出现 clockdiff 报错的解决方案

  1. 确认用户(root 用户及安装用户)是否有执行 clockdiff 命令权限,若没有则执行如下命令添加:setcap cap_net_raw+ep /usr/sbin/clockdiff

  2. 确认 OCP 参数是否正确。
    修改 OCP 平台参数。

  3. 如果没有 clockdiff 命令,手动安装。

案例 – 时钟偏差导致集群故障

现象

  • 用户滚动停 OBServer,进行 RAID 卡版本升级。
  • 执行 zone2 机器时,主机重启后,OBServer 进程拉不起来。
  • 报 Server 正在初始化的错误,无法通过 2881 端口访问该 Server。
  • 应用反馈无法连接数据库。

问题原因

  • 排查 Rootserver 发现提示无主,在多个节点上确认均存在。

  • grep “clock diff time is too large” observer.log 发现大量日志。

  • 确认为节点之间时钟差距过大导致集群故障。

解决方案

  • 重建时钟偏差大的节点,恢复业务。
  • 配置时钟服务,保证机器之间时钟差不能过大。

网络情况检查

  • 检查网卡:ifconfig / ip a
    确保 IP 是静态 IP
  • 检查网络带宽:cat /sys/class/net/网卡名称/speed ,默认单位为 Mbps。
    如果不符合实际情况,手动在 OceanBase 安装目录下创建文件(推荐
# vim /home/admin/oceanbase/etc/nic.rate.config
网卡名称=100000

或者使用 ethtool 手动设置

# sudo ethtool –s eth0 speed 10000
  • 机器之间网络延迟不大于 50ms ,线上 OLTP 环境不大于 2ms。
  • 响应延迟较高场景或核心场景,网卡推荐万兆以上 网卡。
案例 – 网卡速率错误导致替换节点卡住

现象

  • 用户执行节点替换,但是执行了很久一直没有完成。

  • 查看内部表,发现已经报错 4766 和 4737 等错误。

问题原因

  • 查看系统日志,发现网卡速率存在问题,设置的为 76MB/s。

  • 后续确认为网卡速率设置错误,导致替换节点卡住。

解决方案

修改操作系统网卡速率配置。

磁盘检查及规划

磁盘检查: df –hT

  • 建议三块盘,最好物理隔离 ,分别数据盘、事务日志盘、OceanBase 数据库安装盘。
  • TP 场景,磁盘 IOPS 建议不低于 1w
  • 磁盘 16T 以下推荐使用 ext4 格式,当数据超过 16 TB 时,仅支持 XFS 类型。
  • 事务日志盘大小:建议大小设置为 OceanBase 数据库内存的 3 倍到 4 倍 以上。
  • 数据库安装盘大小:预留至少 200G 空间,保存 7 天以上日志。
  • 数据盘大小:根据业务数据推断,对比 MySQL 或者 Oracle,OceanBase 单副本磁盘占用量约为 MySQL 或者 Oracle 的 1/3 -1/4。
  • 不推荐数据盘和日志盘同盘部署,RT 敏感业务,会出现明显响应延迟抖动
案例 - 同盘导致性能受损

现象

问题原因

  • 查看监控图表,发现每次在出现响应延迟和 QPS 下降的时候,都出现了转储操作,同时查看转储视图进一步确认。

  • 和用户确认,data 和 redo 使用了同一块物理盘,并且是普通 SSD,查看物理 IO 耗时,可以看到,转储时 IO 耗时出现明显上涨,特别是 ssstore_write 操作。

解决方案

官方推荐 data 和 redo 分盘,性能要求高的,最好用 Nvme SSD。

修改操作系统配置 (生产环境必须)

  • 修改配置文件:/etc/security/limits.conf ,主要配置系统层面的一些限制。
  • 修改配置文件:/etc/sysctl.conf ,优化系统参数。
  • ARM 环境:关闭 NUMA Balancing、禁用内存回收和重新分配功能。
  • 具体修改配置方式,参考官方文档。

关闭防火墙

Systemctl disable firewalld
Systemctl stop firewalld

关闭 SELinux

  • 修改配置文件:/etc/selinux/config
  • SELINUX=disabled
案例 – 参数未配置正确导致内存泄漏

现象

问题原因

vm.max_map_count 操作系统配置非 OceanBase 建议值,造成 munmap 失败,从而造成内存泄漏。

安装时注意事项

一些推荐

  • 生产环境,OceanBase 默认独占机器 ,不建议和其他应用混部。
  • 极致 TP 场景, OBProxy 不建议和 OBServer 混部,推荐 OBProxy 和业务程序部署在相同机器上。

安装方式(生产环境)

  • OCP 平台安装集群(推荐

    • 企业用户推荐使用 OCP 平台 部署 OceanBase 集群。
    • 图形化管理、监控、运维,简单明了。
    • 大部分管理工作都可以在 OCP 平台完成,降低运维出错概率。
  • OBD 图形化安装集群

    • 个人开发者、边缘业务,可以使用 OBD 安装。
    • OBD 无图形化管理界面,后续运维管理相对复杂。
    • 不推荐 OBD 部署之后,再用 OCP 接管,管理混乱。
  • 集群负载类型,会根据不同的负载类型,填充不同的参数模版。

  • 自定义设置,指定正确的安装路径、数据盘和日志盘路径,以及端口。

  • 建议手动设置以下几个参数:

安装后检查

  • 首先强烈推荐使用 obdiag 进行一次巡检 ,检查各项配置是否合理,集群是否存在隐患 – 前面课程已介绍。
  • 检查集群监控、告警、资源水位等是否正常。

  • 创建业务租户,选择合适的负载类型、Zone 优先级(推荐 Random)、Unit 规格、字符集等。

  • 确认合并与统计信息收集时间点,保证和业务高峰期错开。

  • 修改租户 t1 合并时间为 04:00
    ALTER SYSTEM SET major_freeze_duty_time = ‘04:00' TENANT = t1;
  • 修改周一自动收集统计信息开始的时间在晚上 8 点
    CALL DBMS_SCHEDULER.SET_ATTRIBUTE('MONDAY_WINDOW', 'NEXT_DATE', '2022-09-12 20:00:00’);
  • 周一自动收集统计信息的持续时长为 6 小时
    CALL DBMS_SCHEDULER.SET_ATTRIBUTE('MONDAY_WINDOW', 'JOB_ACTION', 'DBMS_STATS.GATHER_DATABASE_STATS_JOB_PROC()');

其他操作及检查

  • 数据导入完成之后,建议先手动执行一次合并和统计信息收集

  • 如果是自动分区分裂,检查数据导入之后每张表的分区分裂情况。

  • 检查表上的全局索引是否分区 ,如果未分区,可能导致热点等问题。

  • 表上如果有全局索引,避免使用 insert ignore into 语法,目前内核不支持此语法。

  • 业务连接驱动,推荐 JDBC 5.1.47 版本,或不高于 8.0.25。

  • 租户高阶参数调整,如:

    • 转储、合并、负载均衡、统计信息收集工作线程等相关参数。
    • 慢查询、大查询阈值和资源使用量等相关参数。
    • 回收站、undo_retention、SQL 工作区内存、查询超时时间等变量调整。

OceanBase 表设计

OceanBase 表设计包含分区表、索引、复制表、列存、表组等。

分区表 - 手动分区

分区表概述

分区表的概念

OceanBase 数据库可以把普通的表数据按照一定的规则划分到不同的区块内,同一区块的数据物理上存储在一起。这种划分区块的表叫做分区表,其中的每一个区块称作分区。

分区表的使用场景

  • 并行处理:通过分区将一个表的数据分散到多个服务节点上,充分利用分布式多节点的处理能力,提升并行处理的性能。
  • 热点打散:通过分区将对热点数据的访问分散到多个服务节点上,让整个集群的负载更均衡,避免少数节点出现资源瓶颈。
  • 数据管理:通过分区将对表数据的管理从表的维度细分到分区的维度,比如使用 TRUNCATE 分区的操作来替代批量的数据删除。

OceanBase 数据库中分区表的特点

  • OceanBase 数据库自动对表、分区在多个节点间进行负载均衡和多副本容灾。
  • OceanBase 可动态多机扩展,并在分区间并行查询。
  • 分区的分布对业务透明,可以取代 MySQL 的“分库分表”方案。
  • 社区版最大分区数:MySQL 模式由租户配置项 max_partition_num 控制,默认值 8192。
  • 单机分区数支持上限:根据租户内存大小来预估,每 1GB 内存约支持 20000 分区

分区策略

分区键:数据表中每一行中用于计算这一行属于哪一个分区的列的集合叫做分区键。

分区策略

  • OceanBase 支持的分区策略包括范围(Range)分区、列表(List)分区和哈希(Hash)分区
  • OceanBase 支持组合分区,即先使用一种分区策略,然后在子分区再使用另外一种分区策略。

不同分区策略下的分区键选择规则:

  • 分区键必须是主键或唯一键的子集 。只要表有主键,分区键就必须是主键的子集。
  • MySQL 模式下,RANGE、LIST、HASH 的分区键必须是单个列或表达式 ,且必须是整数类型或 YEAR 类型;RANGE COLUMNS、LIST COLUMNS、KEY 的分区键可以是多个列 ,但不支持表达式,并支持除 BLOB、TEXT 外的大部分数据类型。

分区管理

添加分区

  • 对于一级分区表,暂不支持对 Hash 分区和 Key 分区执行添加分区操作。
  • 对于二级分区表,当前仅支持对 Range/List 类型(组合)的分区执行添加分区操作。

删除分区

对于一级分区表,暂不支持对 Hash 分区和 Key 分区执行删除分区操作

对于二级分区表,当前仅支持对 Range/List 类型(组合)的分区执行删除分区操作。

尽量保证待删除的分区上不存在活动的事务。

可通过视图 oceanbase.GV$OB_TRANSACTION_PARTICIPANTS 查询活跃事务。

Truncate分区

对于一级分区表,暂不支持对 Hash 分区和 Key 分区执行 Truncate 分区操作。

对于二级分区表,当前仅支持对 Range/List 类型(组合)的分区执行 Truncate 分区操作。

尽量保证待 Truncate 的分区上不存在活动的事务或查询。

注意:Truncate 分区和 Drop 分区目前会导致全局索引不可用,因此在有全局索引的时候,删除完成之后需要重建分区,后续版本会对这块做优化。

案例 - 分区不均衡导致扩容失败

现象

  • 用户扩容租户,unit_num 从 4 设置为 5,扩容过程中,从 OCP 上观察发现新机器磁盘被打满。
  • 按照当前容量计算,新机器磁盘空间是足够的。
  • 扩容任务卡住,长时间无法恢复。

问题原因

  • 查看内部表,发现扩容任务已经报错,报错码包括 4184、4737等,重点从 4184 可以判断出扩容任务因磁盘满卡住。

  • 接着查看新机器上的日志流,以及对应的 Partition 和表,对表的 Partition 大小统计,发现最大 Partition 800MB,最小 30MB。


  • 因此判断在扩容时,机器上的大 Partition 被迁移过去导致磁盘打满。

  • 解决方案
    提前规划好分区,防止产生明显的大小分区。

  • 无法确定的情况下,建议使用自动分区分裂。

分区表索引 - 局部索引

分区表的局部索引和非分区表的索引类似,索引的数据结构还是和主表的数据结构保持一对一的关系,但由于主表已经做了分区,主表的“每一个分区”都会有自己单独的索引数据结构。局部索引的结构如下图所示,表使用 emp_id 字段做分区。

分区表索引 – 全局索引

分区表的全局索引不再和主表的分区保持一对一的关系,而是将所有主表分区的数据合成一个整体来建立全局索引。

全局索引可以定义自己独立的数据分布模式,既可以选择非分区模式也可以选择分区模式:

  • 全局非分区索引(Global Non-Partitioned Index)
  • 全局分区索引(Global Partitioned Index)

案例 - 全局索引未分区导致机器 CPU 打满

现象

  • 用户执行一个批量写入操作,但是一发起写入,就发现有一台机器的 CPU 被打满。

  • 同时这台机器上的 bloom_filter_cache 请求次数相比其他机器也是异常高。

  • 查看每台机器的写入 TPS,基本都在 4k 左右,没有明显倾斜。

问题原因

  • 排除机器本身因素,从监控中看到这台机器的 bloom_filter 请求次数异常高,怀疑有很多请求打到这个节点。
  • 接着对表进行分析,发现表上有全局索引,并且未进行分区
  • 检查这个全局索引表的 Leader,发现正好就在这台 CPU 高的机器上,因此基本确认。

解决方案

对全局索引表进行分区。

分区表索引 – 索引创建策略

创建索引需要考虑用户访问数据方式、性能、索引可维护性等方面。

  • 如果索引包含主表所有分区字段,推荐使用局部索引。
  • 如果索引不包含主表分区字段,且要求是唯一索引,则需要使用全局索引。
  • 主表未分区,则建议直接使用局部索引。
  • 查询条件包含分区键,则优先选择创建局部索引。
  • 如果主表存在大量 DML 的情况下,使用全局索引会导致更多跨分区的分布式事务,这种场景不建议使用全局索引。
  • TP 场景单表上的全局索引不建议超过3个。

案例 - 无效分区+全局索引导致性能差

场景

  • 之前 MySQL 环境,业务层做了分表,约 500 多张表,每张表上千万行数据。
  • 业务不同意在 OceanBase 上用分区表进行合表。
  • 考虑到 OceanBase 分布式能力,每张表也做了 Key 分区,每张表 32 个分区。
  • 迁移完成,业务切了一部分流量到 OceanBase 上,结果发现响应延迟持续较高,持续有大量超 200ms 的延迟,半小时不见恢复。

问题

  • 流量切到 OceanBase 开始的几分钟,SQL 响应时间上百 ms。
  • 命令行登陆执行非常快,1-2ms 就可以返回,执行计划无异常。
  • 检查发现执行计划生成时间很长,占了超过 90% 的执行时间。
  • 排查发现执行时间久的 SQL 大多没有带分区键,通过创建的全局索引查询。
  • 而未带分区键的查询,OBProxy 会随机发请求到 OBServer 上,导致 SQL 在每个 OBServer 都会做一次硬解析,生成执行计划,用户部署架构是 6-6-6,因此同一个 SQL 有可能生成 18 个执行计划。

解决方案

  • 对于这类在业务层已经做了分表,业务可以确保每张表数据量不会很大,并且各分表之间数据量差异也不大的情况下,可以在OceanBase上不使用分区表,这样也避免了全局索引

分区表-自动分区分裂

自动分区分裂概念

在 OceanBase 数据库中预先设定自动分区规则,在数据增长到一定程度时自动进行分区拆分操作。这样可以让数据库表在数据增长的情况下自动进行扩展,避免单分区数据量过大带来的负载均衡、性能等问题

使用场景

  • 负载均衡:大表如果不分区,会导致数据不均衡,如果手动分区,又没办法找到合适的分区键,因此可采用自动分区分裂的方式;实现大表数据自动分区打散,业务请求均衡;
  • 自动应对业务增长:手动指定分区键或分区范围,随着业务数据增长,可能出现数据不均衡情况,自动分区分裂,会自动将分区大小超过阈值的分区进行分裂,防止出现超大分区;
  • 业务平迁:其他支持自动分裂的KV数据库或者关系型数据库平滑迁移到 OceanBase;
  • 手自一体:支持为单张表独立设置是否开启自动分区分裂,一些场景可以将部分表手动分区,部分表自动分区;
  • 全局索引自动分裂:全局索引单独使用自动分区分裂,全局索引手动分区无法确定分区上下界,或者主表是列存情况。

使用限制

  • 不支持自动分裂 List、Hash 分区表。
  • 不支持自动分裂二级分区表。
  • 不支持被自动分裂的表的分区键与主键前缀不一样。
  • 不支持无主键表的自动分区分裂。
  • 不支持列存表的自动分区分裂。

租户级自动分裂

租户级自动分区

image

表级自动分区

全局索引自动分区

手动分区 VS 自动分区

列存表

列存表原理概述

列式存储:

  • 基线数据存储为列存模式,增量数据保持行存。
  • 用户的所有 DML 操作不受影响,列存表数据仍然可以像行存表一样进行所有事务操作;
  • 每列数据存储为一个独立的 SSTable ,所有列的 SSTable 组合成为一个虚拟 SSTable 作为用户的列存基线数据;
  • 根据用户建表时指定的表的存储模式,基线数据可以有行存、列存、行存列存冗余 三种模式。
  • 列存情况下,可以为表单独创建行存索引,反之亦然。

列存场景建议

  • 列存适合宽表查询和分析场景,压缩率高,可利用 SIMD 加速。
  • 默认为堆表,堆表按插入时间排序,适合 AP 业务中全表扫描场景。
  • 索引组织表适合特定维度频繁查询场景,尤其范围查询。
  • 业务有明显聚合维度,如按时间或用户聚合场景,推荐使用索引组织表。
  • 分区建议:建议一级分区按时间划分,二级分区采用 Hash 方式打散数据。
  • 列存表每列会是一个 SStable,因此分区数不建议过多,建议二级 Hash 分区数为单 zone cpu 数一半。
  • 使用列存,注意合并时间,列存合并时间相比行存会慢,可适当调整合并线程。
  • 列存表排序规则,推荐使用 utf8mb4_bin,性能会更好。
  • AP 场景避免过度依赖索引,尤其多维组合索引,可考虑去掉部分索引。
  • 行列混存主要用于兼容历史系统设计,建议根据原始系统结构选择是否启用。

行存 VS 列存

复制表

复制表概述

复制表的概念 :复制表是 OceanBase 数据库中一种特殊类型的表。复制表会在租户的每一个服务节点上创建一份数据副本,OceanBase 可以在任意一个"健康”的副本上读取到数据的最新修改,而普通表只有主副本才能保证读到最新的数据。

复制表的适用场景

  • 复制表适用于读多写少且数据量较小的表,比如参数表。
  • 复制表用于解决跨机读取数据的性能问题,通过在每个服务节点上复制一份数据,让读请求都可以在本地完成。

OceanBase V4.2 版本中复制表的特点

  • 复制表会在租户的每一个 UNIT 内各创建一个副本,以满足大量并发的读请求。
  • 复制表只有一个 Leader 副本,可以接受写请求;复制表的所有“健康”副本都能接受强一致性读请求。
  • Leader 副本授予所有“健康”副本 Lease,在 Lease 有效期内与所有“健康”副本强同步,保证强一致性读的正确性。

Buffer 表

Buffer 表概述

Buffer 表的概念 :Buffer 表又被称为 Queuing 表,意为业务上“像使用 Buffer 一样使用一张表”。通常情况下,Buffer 表实际的数据量不大,但在业务执行过程中会有大量的更新操作或者插入再增删操作。

Buffer 表效应 :Buffer 表上的查询性能随着更新或者增删次数的增长而越来越差。Buffer 表效应是基于 LSM-Tree 机制实现的存储引擎的通用问题。

  • 在 Memtable 中,记录的多版本记录链表随着更新次数的增加变得越来越长。
  • 默认设置下,删除行的操作只是在内存里打个删除标记,数据到合并时才会真正被删除。当增量数据中积累了大量标记删除的数据时,从上层应用视角实际存在的行很少,但范围查询时可能需要处理较多的标记删除的数据,从而导致 SQL 耗时不够理想。
  • 同时 Buffer 表场景下也容易导致优化器生成非最优执行计划。

OceanBase 的 Buffer 表解决方案

  • 自适应合并:OceanBase 4.2+ 支持分区级的自适应合并,数据库自动检测 Buffer 表行为,并主动发起分区级的合并。通过合并来消除 Buffer 表中的删除记录空洞和多版本数据,缩小 Buffer 表的实际大小,提升查询性能。
  • 表级的合并策略:为了更加灵活地解决 Buffer 表带来的性能下降问题,OceanBase 数据库在 V4.2.3 版本开始支持表级的合并策略。用户可以通过为每张表设置不同的 table_mode 值,以便指定不同的快速冻结与自适应合并策略以应对 Buffer 表的性能问题。

指定 Buffer 表的合并策略 (V4.2.3+)

在创建表或修改表时,通过表选项 table_mode 指定不同模式的自适应合并策略。

示例:指定 Buffer 表的合并策略。

GREATE TABLE tbl1 (c1 int, c2 double) TABLE_MODE = 'queuing';
ALTER TABLE tbl1  SET TABLE_MODE = 'Moderate';

注意:

  1. 修改表的语句执行成功后,系统会有一定的延时(大约2分钟),待修改生效后,系统将以配置的合并模式调度自适应合井以解决 Buffer表现象。
  2. 在 V4.2 版本中,表的 table_mode 属性只能通过 SHOW CREATE TABLE 的方式查看,系统表暂不提供 table_mode 的查询。

案例 – Buffer 表导致查询性能差

现象

场景

  • 业务查询一张表,表数据量不大,只有几十行数据。
  • 随着时间推移,查询的性能越来越差。
  • 查看执行计划,发现物理行扫描超过 200w 行。

问题

  • 经确认,这张表会频繁发生插入和删除操作。
  • 建议将表设置为 Buffer 表,指定 mode 为 extreme 模式。

表组

表组概述

表组的概念

表组(Table Group)是一个逻辑概念,表示一组表的集合。OceanBase 依据表组的 SHARDING 属性控制组内表和分区的物理分布,使表组内的表或不同表的相同分区聚合在相同的服务节点上。

表组的适用场景

通过表组将业务相关联的表按照一定的规则进行物理上的聚合,避免跨节点的数据访问,避免分布式事务,提升查询和交易的性能。

设计规范

表命名设计

  • 避免特殊字符:表名不推荐以下划线开头或结尾,且不推荐以数字开头。
  • 避免使用保留字:不推荐将系统保留字和关键字用作表名。
  • 无数字表名:表名中不应只包含数字介于下划线之间。
  • 保持单数形式:表名应使用单数形式而非复数名词。
  • 一致的字母格式:建议表名使用统一的字母大小写,不推荐混合使用。
  • 语义明确:表名应具有清晰的语义,易于理解。例如:可以使用 test 来表示测试表。
  • 命名结构:表名应以子系统名称或通用标准缩写开头,后接功能描述并用下划线分隔。例如:account_user。
  • 数值标识:若表名后需跟数字标号,建议编号有序递增,从 “00” 开始。例如:account_user_00。
  • 时间分表命名:时间相关的分区表应采用格式 “表名_时间”。时间可使用四至六位的数字缩写。例如:account_user_2201。
  • 中间结果表命名:命名规则应为:“tmp_表名(或缩写)列名(或缩写)创建时间”,如 tmp_account_tbluser_20220224。
  • 备份表命名:命名规则应为:“bak_表名(或缩写)列名(或缩写)创建时间”,如 bak_account_tbluser_20220224。

字段设计1

数值型字段

推荐使用 bigint 类型替代 int、smallint 等整型类型,防止以后范围超限。

字符型字段

  • 所有动态字符串建议全部使用 VARCHAR(N) 类型。
  • 仅仅只有单字符的字段使用 CHAR(1)。表达是与否概念的字段,建议使用 CHAR(1) 类型以节省空间(1 代表 TRUE,0 代表 FALSE),值的内容要统一,所有应用值要统一,例如:表达逻辑删除的字段名 is_deleted,1 表示删除,0 表示未删除。
  • NUMBER(1) 也可以表达是与否的概念,但占用的空间更大些。
  • 列的类型禁止使用 NVARCHAR、NCLOB 等类型。
  • 字符数据类型的列可以存储所有字母数字值,但是 NUMBER 数据类型的列只能存储数字值。

案例 - 索引长度超限

现象

场景

用户创建一张表,接着为这张表上某个字段创建索引,但是创建索引的时候报错:key was too long。

问题原因

OceanBase 索引字段最长为 16384 个字节,name 字段是 8192个字符,表的编码形式为 utf8mb4,假如按照一个字符 4 个字节,那么就会超过 16384 个字节的限制。

解决方案

  • 修改索引为前缀索引。
  • 确认该字段是否需要这么长的存储空间。

字段设计2

日期时间字段

  • 有时间精度要求的业务,可以使用 datetime(6)。
  • 对精度没要求的,设置为 datetime 即可。
  • 如果将来有国际化需求,建议使用 timestamp。
  • 不推荐使用字符作为时间字段的数据类型,在使用的时候容易造成隐式类型转换。

数据字段的选择推荐,特别是在大表上(百万级),推荐如下使用方法:

  • 业务内各表时间字段务必统一,推荐使用 DATE 类型,对于精度较高的业务可以使用 TIMESTAMP 类型。
  • IP 所在表如果是大表,推荐使用 NUMBER 数值类型存储,可节省存储空间。前端进行转换。使用数值范围大小跟网段数据保持一致。
  • 根据业务需要,IPv4 和 IPv6 也可以分字段存储,采用 VARCHAR(N) 存储。

案例 - 隐式转换导致性能上不去

压测现象

场景

  • 业务压测,发现稍微给点流量,响应延迟就直接超时;

  • 从 OCP 上看,QPS 最高才是个位数;

  • 而响应延迟达到了 300ms 。
    image

问题复盘

  • 从执行计划上看,明显不符合预期;
  • 检查表结构和查询 SQL,发现 driver_id 字段是 varchar(200) 类型,而查询 SQL 中将 driver_id 当做了 int 类型,导致查询无法使用上索引;

  • 因此可以得出结论,因为字段类型不匹配,导致性能上不去。

解决方案

  • 查询 SQL 中,将 driver_id 当作字符串处理;
  • 收益:压测流量提升明显,响应延迟回到 10ms 内。

字段设计3

  • 自增列字段:必须使用 bigint 类型,禁止使用 int 类型,以防止存储溢出。

  • 禁止使用外键自引用和级联删除更新的表字段约束定义,以避免重复删除的问题。

  • 尽量避免使用枚举列类型:enum(‘x’,‘y’,‘z’), 应使用字符串类型替代。

  • 如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。

  • 字段允许适当冗余,以提高性能,但是必须考虑数据同步的情况。冗余字段应遵循:

    • 不是频繁修改的字段。
    • 不是超长字段。
  • 发生隐式类型转换时,数值类型的优先级低于时间类型,高于字符和所有其他数据类型。

  • 合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。无符号值可以避免误存负数,且扩大了表示范围,不同的数值范围推荐不同的数据类型,示例如下:

表结构设计规范 1

  • 表结构设计不应该简单遵循三大范式,应该以业务性能为指导,适当进行数据冗余存储,以减少表的关联从而提升业务性能。冗余字段应遵循:

    • 不是频繁修改的字段。
    • 不是 varchar 超长字段。
  • 建表时应该设定主键。

    • 建议使用业务字段做主键或做联合主键,谨慎使用自增列做主键。
    • 如果用户未指定主键,系统会自动生成一个隐藏主键。
  • 建议一些场景加入两字段:gmt_create,gmt_modified。

说明:

gmt_create,gmt_modified 的类型选择 DATE (精确到秒)或 TIMESTAMP WITH TIME ZONE(精确到微秒,且带当前时区信息),可以使用 sysdate 或 systimestamp 函数。

表结构设计规范 2

  • 注释属性:表、字段需包含 COMMENT 属性,确保其他开发人员更好地理解数据结构和含义。
  • 字段约束:表中所有字段应建议设置为 NOT NULL,而业务需求可自定义 DEFAULT 值。
  • 字段一致性:多表中相同列的定义必须一致,JOIN 的关联字段类型应保持一致,避免隐式类型转换。
  • 避免复杂类型:不推荐使用 BLOB 或 JSON 类型数据。
  • 一般不推荐使用主外键关联。
  • 一般不推荐 check 约束。
  • 主外键关联和 check 约束,建议在业务逻辑中实现性能会更好。

分区表设计规范1

分区表创建时的注意事项

  • 如果数据量很大并且访问比较集中时,建议在创建表时使用分区表。

  • 分区表约束注意事项。

    • 建分区表时,表上的每一个主键、唯一键所对应的字段里都必须至少有一个字段包含在表的分区键字段中。
    • 分区表中的全局唯一性建议能通过主键实现的都通过主键实现。
    • 分区表的唯一索引必须包含表分区的分区键。
  • 关于分区策略,推荐从表的实际用途和应用场景方面进行设计。

    • 实际用途:历史表,流水表。
    • 应用场景:存在明显访问热点的表。
  • 关于分区键的选择,使用分区表时要选择合适的拆分键以及拆分策略。这里仅做选择分区类型的基本推荐:

    • Hash 分区:选择区分度较大、在查询条件中出现频率最高的字段作为 Hash 分区的分区键。
    • Range 和 List 分区:根据业务规则选择合适的字段作为分区键,但分区数量不宜过少。示例:如果是日志类型的大表,根据时间类型的列做 Range 分区。

分区表设计规范2

关于分区的使用限制

HASH 分区下,不适合基于分区字段进行范围查询。

分区数建议

  • 数据量逻辑:根据数据量的大小来确定分区数,一般来说,数据量越大,分区数就应该越多,以提高查询和写入的性能。
  • 并行度逻辑:根据系统的并行处理能力来确定分区数,可以根据服务器的 CPU 核数、内存大小等硬件资源来确定分区数,以充分利用系统资源。
  • 分布式扩展吞吐逻辑:根据系统的分布式扩展的需求来确定分区数,可以根据系统的负载和吞吐量来确定分区数,以提高系统的扩展性和性能。
  • 管理粒度对齐逻辑(时间):根据数据的时间特征来确定分区数,可以按照时间范围来划分不同的分区,以方便数据的管理和查询。例如按照年、月、日等时间粒度来划分分区。

业务上线推荐指南

包括上线推荐流程、上线前规划内容、注意事项等。

OceanBase 业务上线推荐流程

应用梳理

应用需求理解

  • 存储、运维成本高
  • 高可用能力差
  • 性能、并发问题
  • 其他需求:向量检索、KV、实时数仓等

应用场景

  • 历史库、归档库
  • 交易流水、账单库
  • 客户信息库
  • 数据汇聚查询分析库等

应用&数据库兼容性评估

  • 业务驱动:推荐使用 JDBC 5.1.47 版本、8.0.25 版本
  • 字符集、字符序:根据业务实际情况选择,如不兼容,可选择包含当前业务字符集的父集,如 utf8 → utf8mb4
  • 数据类型
  • SQL 语法
  • 过程性语言
  • 函数与表达式

注意:禁止使用 sys 租户做测试,需要创建单独用户

业务测试

迁移评估工具 OMA

案例 - 随机 Hint 导致性能上不去

压测实时监控

场景

  • 测试内容:挑选 4 条业务 SQL,按实际生产流量比例对 OceanBase 发压测试。
  • 测试目的:模拟线上流量,测试 OceanBase 极限性能。

现象

  • 现象1:不断增加压测流量,QPS 最高达到 1w+ 的时候,出现 SQL 响应延迟明显上升
  • 现象2:服务器监控看到 CPU 的空闲率在 QPS 最高时直接掉底,CPU 打满
  • 现象3:OCP 监控采集 Agent 进程出现内存告警,进程频繁 OOM

根因定位

  • OCP Agent 内存大部分被 SqlPlan 模块 占用
  • QPS 不高,CPU 被打满,业务 SQL 都是点查点写 ,无复杂计算逻辑;
  • 发现每条 SQL 都带了一个随机 code ,如 select /*+ code:xxx */ ;
  • 业务将随机 Hint 取消之后,整体压测流量可以达到 3w+

案例 - 相同 SQL,不同 SQL_ID

现象

场景

  • 用户一条业务 SQL,每次执行只有 where 条件中的变量不一样,理论上在 OB 中应该生成相同的 SQL_ID,从而命中已有的执行计划,加速查询。
  • 实际上从 gv$ob_sql_audit 中查询看到,每次 SQL 对应了不同的 SQL_ID,导致业务 SQL 每次硬解析,性能差。

问题原因

  • 将表结构和 SQL 拿到本地进行测试,开始未复现。
  • 重新和用户确认,使用了 prepare statement 协议,但是没有使用变量方式,而是把条件直接写死在 SQL 中,这会导致 OceanBase 对 SQL 生成 SQL_ID 时,每次生成不同的 ID,无法命中执行计划。

解决方案

使用变量的方式,将条件传入到 ps 语句中。

案例 - 压测 SQL 偶发超时

现象

现象

  • 用户压测发现,偶尔会有小批量 SQL 执行时间非常长,超过 300ms;
  • 对数据库进行检查,未发现在执行时间长的时间点有什么后台任务,如转储合并、统计信息收集等。

问题原因

  • 查看内部表 gv$ob_sql_audit,找到对应执行慢的 SQL,发现实际在数据库内部处理的非常快;
  • 检查 OBProxy 慢日志中未发现明显的慢 SQL;因此从业务侧进行抓包,发现执行慢的 SQL,实际从数据库发包到收包之间的时间非常快。后排查发现是业务程序内存分配过小,频繁发生 FGC。

解决方案

  • 调大业务程序 JVM。

硬件资源评估

必须部署组件

OBServer

  • 分布式集群:至少三台机器(推荐)。
  • 主备集群:至少两台机器(无法保证 RPO=0 )。
  • 机器配置:生产环境 CPU 最低要求 4C,推荐 32C 及以上,内存最低要求 16G,推荐 32G 以上。
  • 租户配置:至少 4C8G,租户实际大小根据上面性能测试确定。
  • 机器之间网络时延、网口速率、磁盘 IOPS 等检查,生产环境磁盘使用量不超过80%。
  • 资源配置可参考官网链接:https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000002013498

OBProxy

  • 较轻量进程,至少部署 2 个保证高可用。
  • 单独机器部署,至少 4C8G。
  • 与业务程序混部(推荐)。
  • 与 OBServer 服务混部(极致 TP 场景不推荐)。
  • 单独部署 或与 OBServer 混部,需要负载均衡,可使用域名服务、F5、Nginx、Haproxy 等。

可选部署的组件

OMS

  • 无需高可用,单节点部署,单地域单节点。
  • 高可用部署,至少2台机器,单地域多节点 或者 多地域多节点。
  • 需要一个元数据实例,可选 OceanBase MySQL 租户或 MySQL 实例, 2C4G 即可。
  • Docker 软件版本要求不低于 V1.13。
  • 资源规格参考:https://www.oceanbase.com/docs/community-oms-cn-1000000003497681

OCP

  • 需要两个租户,一个 Meta 租户,一个 Monitor 租户,建议和业务集群独立。
  • OCP 进程至少 4C8G,Meta 租户至少 4C8G,Monitor 租户至少 4C16G。
  • OCP 进程资源以及租户规格要求随接管节点数量变化,具体参考: https://www.oceanbase.com/docs/common-ocp-1000000003340280

Binlog 服务

  • 可选单节点 或 高可用部署,节点数量可自己根据情况选择。
  • 需要一个元数据实例,使用 MySQL 或 OceanBase MySQL 租户,2C4G 即可。
  • 节点配置根据性能配置,具体参考:https://www.oceanbase.com/docs/common-oblogproxy-doc-1000000003053717
  • 推荐使用 OCP 平台部署,租户 Binlog 服务也在 OCP 上创建,管理和监控非常方便。

高可用规划

部署方案规划

高可用能力熟悉

数据库高可用能力熟悉

  • OBServer/OBProxy 进程异常退出。
  • OBServer/Obproxy 进程异常挂起。
  • RootSerivce 节点故障。
  • 服务器故障,服务器重启。
  • 磁盘故障。
  • 网络交换机故障。
  • 机房级故障恢复。
  • OCP 管控故障测试。

测试过程中需要关注的指标项

  • 出现故障后,业务受损范围和恢复时长。
  • 出现故障后,业务请求错误率变化。
  • 出现故障后,请求并发和响应延迟受到的影响。
  • 出现故障后,数据是否出现丢失情况。
  • 故障恢复后,响应延迟和并发能否恢复。
  • 故障恢复后,受损的数据副本能否继续同步数据并在同步完成后提供服务。

容灾能力熟悉

数据库容灾能力熟悉

  • 主备租户搭建熟悉。

  • 主备租户 Failover 熟悉。

  • 主备租户 Switchover 熟悉。

  • 备份、归档能力熟悉。

    • 全量备份、增量备份。
    • 租户级备份、表级备份等。
  • 恢复能力熟悉。

    • 全量恢复、指定时间点恢复。
    • 租户级恢复、表级恢复等。
  • 导入、导出能力熟悉。

  • 旁路导入能力熟悉。

注意事项

  • 主备租户之间异步同步,不保证 RPO=0。
  • Failover 之后,需要重新搭建主备关系。
  • 备份、归档需要使用共享存储或对象存储。
  • 备份需要规划好备份集和磁盘空间。
  • 备份之前,必须开启归档。
  • 备份介质连通性确认,可参考:OceanBase 社区
  • 确认备份目录权限,OBServer 进程启动用户是否有读写权限。

案例 – 共享存储目录权限不足导致备份失败

现象

  • 用户通过命令修改归档路径。
  • 修改完成之后查看状态为 Stopping,任务没有正常运行。

问题原因

  • 检查挂载的 NFS 共享路径权限,发现使用 Admin 用户权限不足。
  • 需要确认目录权限,某些情况下,使用 Root 用户挂载的目录,但是 OBServer 进程启动用户如 Admin,没有权限访问,会导致备份和归档失败。
  • 同样对象存储也需要确认权限。

弹性扩缩容熟悉

数据库弹性扩缩容熟悉

  • 增加/删除 OBServer 节点熟悉
  • 增加/删除 OBProxy 节点熟悉
  • 增加/删除 Zone 熟悉
  • 修改租户 Unit_Num 熟悉
  • 修改租户副本数熟悉
  • 修改租户 UNIT 规格熟悉
  • 单机扩展分布式熟悉

以上测试配合持续的压测流量,观察在扩缩容过程中,以下指标变化情况,来判断扩缩容对业务的影响:

  • QPS/TPS 变化
  • 响应延迟变化
  • 请求失败率变化等

数据迁移

数据库迁移能力

  • 全量迁移
  • 增量同步
  • DDL同步
  • 数据校验
  • 数据链路回写
  • 多表汇聚同步
  • 对象映射转换
  • 数据过滤
  • 迁移链路添加、删除对象
  • 迁移链路启动、暂停
  • 指定增量位点同步

注意事项

  • 数据校验,表上必须有主键或非空唯一键。
  • 表主键不连续,空隙大,可指定其他字段用于 OMS 切片。
  • 多表汇聚,注意主键冲突,需考虑过滤主键,同时需要考虑合表之后原唯一键冲突。
  • 大表全量同步,建议选用旁路导入方式。
  • 如果遇到其他问题,可学习前面 OMS 课程,寻找解决方案。

案例 – 多表聚合后唯一键冲突导致丢数据

现象

MySQL 查询结果

OceanBase 查询结果

  • 数据同步源端是分库分表,有多张表,使用 OMS 多表汇聚功能,同步到 OceanBase 的一张分区表上。
  • 同步完成之后,发现少了数据,相同查询条件,MySQL 查出来3行结果,OceanBase 查出来只有1行。

问题原因

  • 源端是多张表,表上有唯一键,但是这个唯一只能保证分表上的唯一,无法保证多张表汇聚之后依旧唯一。
  • 使用 OMS 同步时,选择了忽略冲突。
  • 因此多表汇聚的时候,一定要确认好唯一键在合并之后是否冲突,或者在同步任务中选择冲突时停止同步。

业务上线建议

  • OMS 支持完整的正向切换和反向增量,如果用到这些功能,建议完整测试。
  • 对 OceanBase 不熟悉用户,建议先从边缘业务开始。
  • 上线前,对日常运维的一些操作建议完整测试,多熟悉 OCP 功能。
  • 上比较核心业务之前,建议先通过 OBCP 认证考试。
  • 测试或线上遇到问题,可通过官网问答区:ask.oceanbase.com 或钉钉群提问。

其他功能熟悉

  • DDL 变更能力

  • 回收站功能

  • 闪回功能

  • 数据库升级能力

  • 其他功能性

    • 物化视图
    • 全文索引、向量索引等
    • 列存表、列存索引等
    • 手动分区、自动分区
22 个赞

跟上OceanBase的前进步伐。加油!!!!

21 个赞

从问题分析看,OceanBase的DBA需要好好修炼啊。

22 个赞

加油 ! :+1: :+1:

20 个赞

已学习+1

21 个赞

:+1: :+1: :+1:

19 个赞

:call_me_hand: :call_me_hand: :call_me_hand:

20 个赞

OceanBase PoC 与业务上线提效指南

21 个赞

大佬这是多么用心啊,整理地这么详实

25 个赞

感谢分享

24 个赞

各种问题,整理到一起吧。

22 个赞

弄一个问题处理集锦。

18 个赞

学到了

16 个赞

学习了学习了

15 个赞

:+1: :+1: :+1:

15 个赞

太好了

11 个赞

:grinning: :grinning: :grinning:

11 个赞

来了来了

11 个赞

来了来了

12 个赞

学习了

8 个赞