Oracle 没报错,CPU 也不高,业务为什么卡成这样?

简介: 业务卡顿时,CPU 低并不代表数据库没问题。本文还原一次从 AWR、ASH 到 RMAN、磁盘与 RAID 的完整实战排查过程,并附上可直接复用的查询脚本。 前言 前段时间遇到一个 Oracle 数据库卡顿问题。 业务反馈系统突然变得很慢,打开页面要等,提交也要等,但是没有明确报错。登录主机看了一下

业务卡顿时,CPU 低并不代表数据库没问题。本文还原一次从 AWR、ASH 到 RMAN、磁盘与 RAID 的完整实战排查过程,并附上可直接复用的查询脚本。

前言

前段时间遇到一个 Oracle 数据库卡顿问题。

业务反馈系统突然变得很慢,打开页面要等,提交也要等,但是没有明确报错。登录主机看了一下,数据库实例正常,CPU 也不高,Idle 甚至接近 99%。

从主机监控看,这台服务器完全不像正在出故障,但业务确实已经卡住了。

这种问题通常比直接报 ORA 错误更麻烦。没有错误信息,只能从故障时间点开始,一层一层往下查。本文记录一下当时的分析和处理过程。

问题分析

首先,根据业务反馈的时间段生成了一份 AWR 报告。

报告窗口大约 59 分钟:

Elapsed Time : 59 min
DB Time      : 309 min

Average Active Sessions 大约是 5.2。服务器有 64 个逻辑 CPU、32 个 Core,再看 CPU 使用情况:

AWR Host CPU:CPU Idle 为 99.1%

AWR Host CPU:故障时间段 CPU Idle 为 99.1%,主机并没有出现 CPU 忙的问题。

CPU 确实很空闲,但是 59 分钟的报告窗口里,DB Time 却有 309 分钟,说明数据库会话大部分时间不是在消耗 CPU,而是在等待。

继续看 AWR 的 Top Foreground Events:

AWR Top 10 Foreground Events:log file sync 平均等待 431ms

AWR Top 10 Foreground Events:log file sync 占 54.9% DB Time,平均等待 431ms。

第一名是 log file sync,占了 54.93% 的 DB Time,平均等待 431ms。

前台会话提交事务时,需要等待 LGWR 将 redo 写入联机日志。现在一次 COMMIT 平均要等 431ms,业务页面点一下、顿一下也就说得通了。

接着查看对应的后台等待 log file parallel write

log file parallel write
Waits          25,954
Time Waited    1,359 sec
Avg Wait       52 ms

LGWR 平均一次写要等 52ms,这个延迟已经明显不正常。AWR 中还有两个写等待也很高:

control file parallel write      ≈ 197 ms
db file async I/O submit         ≈ 364 ms

看到这里,我首先怀疑的是存储。因为慢的不只是业务 SQL 读取,redo 和 controlfile 写入也慢。

不过 log file sync 高也可能和业务提交频率有关,现在还不能直接认定是硬件问题,还要看看故障时间段内有没有其他任务在大量做 I/O。

RMAN 正好也在跑

继续看 ASH,Top Background Events 中有一个等待非常显眼:

ASH Top Background Events:RMAN backup recovery I/O 活跃度最高

ASH Top Background Events:RMAN backup & recovery I/O 的活动占比为 20.03%,平均活跃会话为 1.98。

Top Sessions 中还看到了两个 RMAN Channel:

ASH Top Sessions(账号与 SID 已脱敏)

Session       Program                    Event                         Active Samples
------------  -------------------------  ----------------------------  --------------
<RMAN-CH-1>   rman@<db-host>             RMAN backup & recovery I/O      3544 / 3600
<RMAN-CH-2>   rman@<db-host>             RMAN backup & recovery I/O      3578 / 3600

两个 Channel 的活跃采样比例分别接近 98% 和 99%。也就是说,业务卡顿的这一个小时,它们基本一直在执行备份。

先从数据库确认 RMAN 会话:

set lines 220 pages 100
col program format a40
col module  format a30
col action  format a30
col event   format a35

select sid,
       serial#,
       username,
       status,
       program,
       module,
       action,
       event
from v$session
where lower(program) like '%rman%'
   or lower(module)  like '%rman%'
   or lower(action)  like '%backup%'
order by sid;

两个会话都是 ACTIVE:

ACTION                 EVENT
backup incr datafile   RMAN backup & recovery I/O
backup incr datafile   RMAN backup & recovery I/O

操作系统上也能找到对应的 RMAN 进程和计划任务:

ps -ef | grep -i '[r]man'
crontab -l

计划任务每周执行一次 Level 0,其余日期执行 Level 1 cumulative。故障时运行的是两通道 Level 1,同时备份数据库和归档日志。

核心脚本大致如下,路径已经脱敏:

run {
    allocate channel c1 type disk;
    allocate channel c2 type disk;

    backup incremental level 1 cumulative database
        format '<backup_dir>/db_%U.bkp';

    backup archivelog all
        format '<backup_dir>/arch_%U.bkp';

    release channel c1;
    release channel c2;
}

RMAN 的执行时间和业务卡顿时间完全重合,确实很可疑。但是到这一步,只能证明 RMAN 在持续做 I/O,还不能证明它就是这次故障的根因。

继续到操作系统看磁盘:

iostat -x 1 20

目标设备多次接近 100% util,队列持续堆积,随机读延迟出现过:

188 ms
365 ms
694 ms
1096 ms

与此同时,CPU Idle 仍然超过 90%。

从这些数据看,RMAN 大概率把磁盘 I/O 压满了,LGWR 和业务 SQL 都在后面排队。但是这个判断还需要验证一下。

停掉 RMAN 之后,问题只解决了一半

停止 RMAN 前后数据库等待变化的手绘对比图

停止 RMAN 后 I/O 压力下降,但异常等待没有完全消失。

当时业务还在受影响,和客户确认之后,决定先停止本次 RMAN 备份,看看等待是否会恢复。

停止之前先确认了本次备份类型、上一份可用备份、中断之后对 RPO 的影响以及后续补跑时间。正常情况下应该优先从 RMAN 客户端或者调度器取消任务,只有失去控制时,才从数据库终止会话。

alter system kill session '<sid>,<serial#>' immediate;

两个 Channel 退出之后,分别从数据库和操作系统进行确认:

select sid,
       serial#,
       status,
       program,
       module,
       action,
       event
from v$session
where lower(program) like '%rman%'
   or lower(module)  like '%rman%';
ps -ef | grep -i '[r]man'

接着查看实时等待。数据库版本是 11g,这里还踩了一个小坑:这个版本的 V$EVENTMETRIC 不能直接使用 EVENT_NAME 查询,需要关联 V$EVENT_NAME

另外,TIME_WAITED 的单位是百分之一秒,换算平均等待毫秒时,需要乘以 10 再除以等待次数。

set lines 220 pages 100
col event_name format a35

select en.name event_name,
       em.wait_count,
       em.time_waited,
       round(em.time_waited * 10 /
             nullif(em.wait_count, 0), 2) avg_wait_ms,
       em.num_sess_waiting
from v$eventmetric em
join v$event_name en
  on em.event# = en.event#
where en.name in (
      'log file sync',
      'log file parallel write',
      'db file sequential read',
      'db file parallel read',
      'read by other session',
      'direct path read',
      'control file parallel write'
)
order by em.time_waited desc;

RMAN 停止之后,实时窗口中的等待变成了:

V$EVENTMETRIC(RMAN 停止后实时窗口)

EVENT_NAME                   WAIT_COUNT   AVG_WAIT_MS   NUM_SESS_WAITING
---------------------------  -----------  ------------  ----------------
log file sync                       <n>          9.42               <n>
log file parallel write             <n>          2.87               <n>
db file sequential read             <n>         42.88               <n>

其中两个等待变化非常明显:

log file sync
431 ms  →  9.42 ms

log file parallel write
52 ms   →  2.87 ms

这说明 RMAN 确实对提交链路造成了很大影响。停止两个 Channel 后,LGWR 写延迟和前台 COMMIT 等待都恢复了。

但是 db file sequential read 仍然有 42.88ms。

RMAN 已经停了,数据文件的单块读为什么还是这么慢?看来问题还没有结束。

几十个 IOPS,磁盘却跑到了 100%

先重新查看数据库活动会话:

set lines 220 pages 100
col username format a15
col event    format a35
col program  format a40

select sid,
       serial#,
       username,
       status,
       sql_id,
       event,
       wait_class,
       seconds_in_wait,
       program
from v$session
where status = 'ACTIVE'
  and type = 'USER'
order by seconds_in_wait desc;

RMAN 会话已经消失,但是业务 SQL 仍然在等待:

db file sequential read
read by other session
db file parallel read

操作系统继续使用 sar 观察磁盘:

sar -d 1 20

平均结果大致如下:

tps        ≈ 60
avgqu-sz   ≈ 2.4
await      ≈ 40 ms
%util      ≈ 100%

这个结果有点反常。设备只有几十个 IOPS,吞吐量也不高,%util 却接近 100%,平均响应时间仍然有 40ms。

再使用 pidstat 看一下具体是谁在读写:

pidstat -d 1 20

最大的几个 Oracle 进程每秒也只有几百 KB,并没有发现另一个隐藏的大吞吐任务。

到这里,前面的判断就需要改一下了。

RMAN 不是简单地把一块正常磁盘跑满。更可能是这块存储本身已经很慢,RMAN 的持续读写又把问题放大了。

这也是本次排查比较关键的一个转折。如果看到停掉 RMAN 后业务恢复,就直接把故障原因写成“备份抢占磁盘”,那么底层问题仍然会留在那里。下一次备份或者业务高峰到来时,问题大概率还会出现。

数据文件、Redo 和备份都在同一组盘

数据库文件、Redo 与 RMAN 备份共享同一存储路径的手绘示意图

数据文件、Redo 和备份共用一组盘,任何后台 I/O 都可能放大业务等待。

接下来检查 Oracle 文件和备份目录分别落在哪里。

先查 redo:

set lines 220 pages 100
col member format a120

select l.group#,
       l.thread#,
       l.bytes / 1024 / 1024 size_mb,
       l.status,
       f.type,
       f.member
from v$log l
join v$logfile f
  on f.group# = l.group#
order by l.group#, f.member;

再查 datafile 和 controlfile:

set lines 220 pages 200
col file_name format a120

select tablespace_name,
       file_id,
       file_name
from dba_data_files
order by tablespace_name, file_id;

select name
from v$controlfile;

操作系统侧将这些路径映射到实际块设备:

lsblk -o NAME,KNAME,MODEL,SIZE,ROTA,TYPE,FSTYPE,MOUNTPOINT
df -hT
findmnt -T <redo_file>
findmnt -T <datafile>
findmnt -T <rman_backup_dir>

服务器对外呈现的是一个十几 TB 的 RAID Virtual Disk,块设备为 sda,主要目录都挂载在 /u01。再查看介质标识:

cat /sys/block/sda/queue/rotational

返回值为 1,后端使用的是旋转介质。

脱敏后的文件布局如下:

Datafile      /u01/...
Online Redo  /u01/...
Controlfile  /u01/...
RMAN Backup  /u01/backup/...

目录看起来是分开的,最终却全部落到了同一个块设备:

/u01
  ↓
sda
  ↓
同一套 HDD RAID

数据库从这组盘读取 datafile,LGWR 往同一组盘写 redo,RMAN 又从这组盘读取数据库,再将备份写回这组盘。两个 Channel 同时运行时,业务随机读、redo 同步小写和备份 I/O 全部挤在了一起。

现在已经可以解释 RMAN 为什么会明显放大延迟,但还不能解释 RMAN 停止之后,设备为什么仍然以很低的 IOPS 跑出 40ms 的 await。

只能继续往硬件层查。

dmesg | grep -Ei 'megaraid|degraded|predictive|failed|offline|rebuild'

grep -Ei 'megaraid|degraded|predictive|failed|offline|rebuild' \
    /var/log/messages*

日志中多次出现下面的信息:

megaraid_sas ... CRIT - VD <id> is now DEGRADED

到这里,前面那些看起来有点矛盾的现象就能解释得通了。

不过这条日志只能证明 RAID Virtual Disk 出现过降级,不能仅凭一条历史日志就断定查询当时阵列仍然处于 Degraded,也不能确定是哪一块物理盘有问题。

后续还需要登录服务器带外管理或者使用 RAID 管理工具,继续检查 Virtual Disk、Physical Disk、Predictive Failure、Media Error、Rebuild、Hot Spare 和 Controller Cache 状态。

在这些状态没有确认之前,没有重启服务器,也没有尝试 Offline、Force Online、Clear Foreign 或重新初始化阵列。阵列已经丢失冗余时,操作错误很可能把一次性能故障变成数据不可用。

OGG 不是这次卡顿的主要原因

这套数据库还运行着 GoldenGate,所以排查过程中也检查了 Integrated Extract 和 LogMiner 会话。

set lines 220 pages 100
col program format a40
col module  format a35
col event   format a40

select sid,
       serial#,
       username,
       status,
       program,
       module,
       event,
       wait_class,
       seconds_in_wait
from v$session
where lower(program) like '%extract%'
   or lower(program) like '%replicat%'
   or lower(module)  like '%goldengate%'
   or lower(program) like '%logminer%'
order by status, seconds_in_wait desc;

当时能看到 LogMiner reader、builder、preparer 和 client 等进程,但是大多数处于空闲等待,没有发现与故障时间段相匹配的大量活动 I/O。

OS 侧也可以继续观察:

pidstat -d 1 20 | egrep 'extract|replicat|oracle|PID'

如果 OGG trail 和 checkpoint 也位于 /u01,它肯定会产生长期 I/O,不过从现场数据看,它不像这次突发卡顿的主要触发者,所以没有为了排除问题而直接停止复制链路。

写在最后

回顾一下整个故障过程。

故障期间,主要等待如下:

log file sync            ≈ 431ms
log file parallel write  ≈ 52ms
db file sequential read  ≈ 65ms
RMAN 两个 Channel        ≈ 98% / 99% 活跃
sda                      ≈ 100% util
r_await                  多次达到数百毫秒

停止 RMAN 之后:

log file sync            ≈ 9.42ms
log file parallel write  ≈ 2.87ms
db file sequential read  ≈ 42.88ms
sda                      仍接近 100% util

从前后对比可以确认,两个 RMAN Channel 是本次业务卡顿的放大因素。它停止后,LGWR 写延迟和前台 COMMIT 等待很快恢复了。

但 RMAN 不是全部原因。数据文件单块读仍然接近 43ms,磁盘在只有几十个 IOPS 的情况下依旧接近 100% util,再结合文件布局和 RAID 降级日志,底层存储状态才是后续需要优先确认的问题。

当时也有人提出要不要重启数据库,我没有同意。重启修不好 RAID,也改变不了 datafile、redo 和 RMAN 共用一组盘的现状,还会清空大约 41GB 的 Buffer Cache。数据库重新启动之后,大量数据需要重新从磁盘读取,在单块读仍然接近 43ms 的情况下,冷缓存阶段很可能比重启之前更慢。

当然,这次问题到这里还没有完全结束。RAID 当前状态、具体故障盘以及后续存储整改方案,还需要结合控制器管理界面进一步确认。

本文记录一下这次 Oracle 卡顿的实际分析过程。很多数据库性能问题不一定会报 ORA 错误,也不一定会把 CPU 跑满。看到一个可疑任务停止后指标有所恢复,也不要急着结束排查。如果还有指标没有恢复,就继续沿着文件系统、块设备和硬件往下找。

好了,本次分享就到这了~

相关文章
|
9天前
|
人工智能 自然语言处理 安全
阿里云千问办公、Qoder Teams、Qoder CN区别与选择指南:模型能力、适用场景与最新活动参考
本文聚焦阿里云2026年推出的三款自研AI办公产品,清晰拆解千问办公、Qoder Teams、Qoder CN的差异化定位与能力边界:千问办公主打职场全场景提效,支持自然语言指令一键完成PPT生成、数据分析等高频办公任务;Qoder Teams面向程序员团队,深度整合AI代码生成、团队协同与企业知识库能力;Qoder CN则专为金融、政务等强合规场景打造,实现数据不出境与VPC私有化部署。文章同步给出分场景选型指南与最新活动定价,帮助不同类型的企业按需组合产品,实现业务岗、研发岗与强合规场景的AI能力全覆盖。
阿里云千问办公、Qoder Teams、Qoder CN区别与选择指南:模型能力、适用场景与最新活动参考
|
21天前
|
人工智能 缓存 前端开发
DeepSeek Harness 首发实测 + 入门教程,夯爆了!梁神我错了
DeepSeek Harness + DeepSeek V4 Pro 项目实战保姆级教程!手把手带你从零安装开源 AI 编程工具,开发架构图、知识讲解网站、3D 网页游戏、全栈 AI 应用 4 个项目,覆盖运行模式选择、插件安装与开发,看看能不能对标 Claude。
13291 91
DeepSeek Harness 首发实测 + 入门教程,夯爆了!梁神我错了
|
14天前
|
Web App开发 人工智能 API
16 个超火的 DeepSeek Harness 插件,大肥鱼已经落后 N 个版本了。。。
DeepSeek Harness 精选插件推荐合集,从图片识别、浏览器操控、多 Agent 协作到手机远程控制,一口气带你看完 DSH 社区热门的十几个插件,覆盖技能扩展、UI 界面增强、整活玩法三大类,让你的鲸鱼变得更强。
1815 4
|
15天前
|
人工智能 Java BI
【AI】DeepSeek Harness 安装、运行、管理插件
本文介绍了如何运行DeepSeek开源的Agent框架DeepSeek Harness(dsh)。主要内容包括:使用nvm安装适配的Node版本;通过代理加速克隆GitHub源码;使用pnpm安装依赖并启动项目;配置DeepSeek API Token;安装扩展功能的插件。该框架自带Web界面,支持模型适配、文件编辑等插件化功能
2015 1
|
9天前
|
人工智能 Linux iOS开发
Ollama使用教程:Ollama官网下载、Ollama本地部署大模型(2026最新)
Ollama 是一款免费开源的本地大模型运行工具,支持在 Windows/macOS/Linux 上离线运行 Qwen、DeepSeek、Llama 等主流开源模型,数据不出本机、隐私安全。提供 OpenAI 兼容 API,命令行一键拉取/运行/管理模型,无需联网,无调用限制,是开发者与 AI 爱好者部署本地 AI 助手的理想选择。(239 字)
|
人工智能 JavaScript 开发工具
DeepSeek Harness 本地安装与使用指南
DeepSeek Harness(DSH)是DeepSeek AI开源的Agent运行框架,支持本地文件操作、命令执行与工具调用。基于Cordis插件架构,具备高扩展性与强可控性,适合开发者搭建可控Agent环境或开展模型基准测试。当前为开发者预览版,需Node.js环境,推荐先用`npx @deepseek-ai/dsh web`快速体验。
5282 0
|
6天前
|
人工智能 监控 测试技术
Qwen3.8-Flash 来了,100万上下文、Agent、Coding 都加强了
8月26日,通义千问发布Qwen3.8-Flash-Next:125B参数、每Token仅激活6B,原生支持26万Token、可扩展至100万上下文;Coding、Agent与工具调用能力显著增强,面向真实软件工程任务,推动大模型从“回答问题”迈向“完成工作”。