怎么定位消耗内存最大的 SQL、会话或模块,以及常见的解决手段。
OceanBase 内存不足与租户内存超限:诊断与调优指南
当 OceanBase 数据库出现“内存不足”或“租户内存超限”告警时,需系统化地从告警类型识别 → 内存分布分析 → 高消耗 SQL/会话定位 → 调优手段实施四个层面进行排查与优化。
一、常见内存问题及初步诊断
根据 产品 FAQ → 内存 FAQ 的描述,常见的内存异常包括:
| 问题类型 | 错误码/报错信息 | 原因分析 |
|---|---|---|
| 工作区内存不足 |
ORA-04036: PGA memory used by the instance exceeds PGA_AGGREGATE_LIMIT 或类似提示 |
工作区(Work Area)内存受限于 租户内存 × ob_sql_work_area_percentage(默认5%),在执行 SORT, GROUP BY, UNION 等操作时易触发 |
| 租户内存超限 | 客户端报错 "Over tenant memory limits",错误码 4013 |
租户整体内存使用达到上限,可能是某模块(mod)持续增长导致 |
| MemStore 内存耗尽 | 错误码 4030 | 写入速度 > 转储速度,导致 MemStore 满,无法接受新写入 |
| OBServer 节点内存超限 | 日志中出现 server memory has reached the upper limit
|
整体节点内存配置不合理或存在内存泄漏 |
日志关键词快速定位:
ctx memory has reached upper limit:上下文内存超限tenant memory has reached the upper limit:租户内存超限server memory has reached the upper limit:服务器总内存超限physical memory exhausted:物理内存不足
来源:产品 FAQ → 内存 FAQ → OceanBase 数据库进行一次内存分配会检查哪些限制?
– 查询所有节点的内存使用情况,按大小降序排列 SELECT SVR_IP, MOD, SUM(HOLD) AS total_hold, SUM(USED) AS total_used FROM GV$OB_MEMORY WHERE TENANT_ID = <your_tenant_id> GROUP BY SVR_IP, MOD ORDER BY total_used DESC;
2. 定位高内存消耗的 SQL 语句
OceanBase 提供了兼容 Oracle 的性能视图,可通过以下方式查找内存消耗高的 SQL:
使用 GV$OB_SQLSTAT 视图(推荐)
此视图记录了 SQL 的运行统计信息,包含内存使用字段。
-- 查找当前租户中平均工作区内存最高的前10条 SQL
SELECT
SQL_ID,
SQL_TEXT,
AVG_MEM_USED,
MAX_MEM_USED,
EXECUTIONS,
ELAPSED_TIME / EXECUTIONS AS avg_time_us
FROM GV$OB_SQLSTAT
WHERE TENANT_ID = <your_tenant_id>
AND LAST_ACTIVE_TIME > SYSDATE - 1/24 -- 近1小时活跃
ORDER BY MAX_MEM_USED DESC
LIMIT 10;
注意:若 SQL 被频繁执行且每次使用大量内存(如大表 JOIN、排序),即使单次未溢出,累积也可能导致租户内存超限。
– 查看当前会话及其执行的 SQL 和等待事件 SELECT SID, SESSION_ID, SQL_ID, CLIENT_IP, CONNECT_TIME, LAST_ACTIVE_TIME FROM GV$SESSION WHERE TENANT_ID = <your_tenant_id> AND STATUS = ‘ACTIVE’;
三、常见调优手段
1. 调整工作区内存比例
对于频繁执行复杂查询的场景,可适当提升 ob_sql_work_area_percentage:
-- 设置全局参数(建议逐步调整,避免过度分配)
ALTER SYSTEM SET ob_sql_work_area_percentage = 10 TENANT = <tenant_name>;
默认值为 5%,最大不超过 90%。调整后需观察整体内存使用趋势,防止其他模块内存被挤压。
2. 优化高内存 SQL
针对定位到的高内存 SQL,采取以下措施:
- 添加索引:减少全表扫描,降低数据处理量
-
拆分大查询:将大结果集的
GROUP BY或JOIN拆分为分批处理 -
启用落盘机制:确保
work_area支持 spilling(默认开启),避免内存溢出直接失败 -
使用 Hint 控制执行计划:例如指定 join 方式为
MERGE JOIN或NESTED LOOP以降低内存需求
3. 检查并优化 MemStore 行为
如果 GV$OB_MEMSTORE 显示 MemStore 使用过高:
SELECT * FROM GV$OB_MEMSTORE WHERE TENANT_ID = <your_tenant_id>;
可考虑:
- 增加转储线程数:
alter system set minor_freeze_times = 10; - 手动触发转储:
alter system minor freeze tenant = <tenant_name>; - 调整
memstore_limit_percentage防止单租户占满共享资源