ITPub博客

首页 > 数据库 > Oracle > 第64期 ORA-00600: internal error code, arguments: [qosdExpStatRead

第64期 ORA-00600: internal error code, arguments: [qosdExpStatRead

原创 Oracle 作者:pxbibm 时间:2026-05-29 15:17:27 0 删除 编辑

2026年5月29日收到数据库系统报警,报警信息  The result is ORA-00600: internal error code, arguments: [qosdExpStatRead: expcnt mismatch], [65539], [3], [481407], [1], [], [], [], [], [], [], [].

报警现象:

从数据库报警信息上分析ORA-600 qosdExpStatRead,那么qosdExpStatRead是什么意思,首先给大家解释一下,方便分析错误产生的原因。

QOSD 是什么?

QOSD = Quality of Service Daemon,Oracle 内部的 服务质量守护进程 / 模块,主要管:
  • 数据库 自动统计信息收集(Auto Stats)

  • 统计信息快照 / 历史管理
  • SQL 调优集(STS)
  • 统计信息导出 / 导入(DBMS_STATS.EXPORT/IMPORT_STATS)
  • RAC 下多节点间的 统计信息同步 Oracle
它在后台跑,会定期把表 / 索引的统计信息 “打快照”、存历史,方便:
  • 对比性能变化

  • 回滚统计信息

  • AWR / 调优工具分析历史负载

“QOSD 统计导出” 指的是什么?

报错里的 qosdExpStatRead → ExpStat = Export Statistics,就是:
QOSD 负责把 统计信息快照导出、写入数据字典表:
  • sys.exp_obj$:每个对象 + 快照的 元数据 + 计数器(EXP_CNT)
  • sys.exp_stat$: 明细数据,一条一条的统计项
简单说:
  • 每次自动统计 / 手动 EXPORT_STATS → QOSD 写 exp_stat$ 明细
  • 写完后更新 exp_obj$ 里的 EXP_CNT(记录明细条数)

为什么会触发你那个 ORA-600?

核心是因为是oracle的一个小  Bug 28681153 :

  • 当多个会话 同时对同一个对象做:如下操作时
  • 自动统计收集

  • 手动 DBMS_STATS.GATHER_*

  • expdp 导出统计

  • EXPORT_STATS 快照导出

QOSD 先写明细 exp_stat \(,后更新 exp_obj\).EXP_CNT

没有锁保护,并发时:

  • 会话 A:插入明细 → 还没来得及更新 EXP_CNT

  • 会话 B:又插入明细 → 更新 EXP_CNT

  • 结果: EXP_CNT ≠ 实际明细行数

下次 QOSD 读取校验 → expcnt mismatch → ORA-600

oracle数据库19c 里因为:
  • 自动统计更激进、默认开启

  • RAC 节点间同步更频繁

  • 校验更严格(11g/12c 可能不报错)所以这个问题在 19c 特别常见。

系统数据字典表 sys.exp_obj$ 的计数器字段 EXP_CNT,和明细表 sys.exp_stat$ 的实际记录行数不一致,Oracle 内部校验不通过,直接抛 ORA-600。
  • sys.exp_obj$: 统计信息快照的 “元数据表”,每条记录记一个对象 + 快照的统计条目总数( EXP_CNT)
  • sys.exp_stat$: 统计信息快照的 “明细数据表”,存每一条统计数据


解决方案:

1、紧急修复步骤

1)定位不一致记录(SYS 执行)

With b as (
select count(*) cnt,objn,snapshot_id from sys.exp_stat$ es group by
objn,snapshot_id)
select * from sys.exp_obj$ a, b where a.objn=b.objn and
a.snapshot_id=b.snapshot_id
and a.EXP_CNT<>b.CNT;
 
       OBJN SNAPSHOT_ID    EXP_CNT        CNT       OBJN SNAPSHOT_ID
---------- ----------- ---------- ---------- ---------- -----------
    6760972           1          0      65536 6760972           1

返回结果即为 有问题的对象号 + 快照 ID

2)修复字典不一致(替换 &SNAP_ID / &OBJN)

先备份(安全第一)
-- 备份异常数据,防止意外
CREATE TABLE sys.exp_obj_bak AS SELECT * FROM sys.exp_obj$;
CREATE TABLE sys.exp_stat_bak AS SELECT * FROM sys.exp_stat$;
delete from sys.exp_stat$ b
where b.snapshot_id = <snapshot_id> and b.objn = <objn> ;
 
update sys.exp_obj$  a
set a.EXP_CNT=0
where a.SNAPSHOT_ID= <snapshot_id>
           and a.objn = <objn>;
 
commit;

注意:这是修改系统字典, 操作前务必备份数据库

3)临时关闭自动统计(防止复发)

-- 关闭自动SQL调优任务
EXEC DBMS_AUTO_TASK_ADMIN.DISABLE(client_name=>'SYS_AUTO_SQL_TUNING_TASK',operation=>NULL,window_name=>NULL);
-- 或仅关闭统计收集(按需)
EXEC DBMS_STATS.SET_PARAM('AUTO_STATS_TASK','FALSE');

4)彻底根治:打补丁 / 升级

  • 19c:升级到 19.7+ RU,或安装 Patch 28681153
  • 若补丁已打仍报错(19.16 等):
ALTER SYSTEM SET "_fix_control"='31143146:on' SCOPE=BOTH;

2、执行后验证(确认修复干净)

-- 检查是否还有不一致
WITH stat_cnt AS
 (SELECT objn, snapshot_id, COUNT(*) real_cnt
    FROM sys.exp_stat$
   GROUP BY objn, snapshot_id)
SELECT '仍有异常' AS result
  FROM sys.exp_obj$ o
  JOIN stat_cnt s
    ON o.objn = s.objn
   AND o.snapshot_id = s.snapshot_id
 WHERE o.exp_cnt <> s.real_cnt
   AND ROWNUM = 1;

输出 无数据行表示已经修复成功了。

3、彻底解决方法

-- 关闭有问题的 QOSD 统计导出(官方推荐规避方案)
ALTER SYSTEM SET "_exadata_feature_on"=FALSE SCOPE=SPFILE;
-- 19c 推荐开启修复控制
ALTER SYSTEM SET "_fix_control"='31143146:ON' SCOPE=BOTH;

Knowledge Article.zip

上面的文档是官方提供的bug修复方案


该问题主要是oracle官方的一个bug引起的。我们虽然修复了bug。但是没有激活Bug31143146 。

因此第二种修复方案如下:

Turn on the fix control of patch 31143146 by set "_fix_control"='31143146:on' :

1. Check the existing "_fix_control" settings:

For example:

--Check SPFILE setting

SQL> select name, value from V$SYSTEM_PARAMETER2 where name like '_fix_control';

NAME VALUE
------------------ ------------------
_fix_control 32005394:on

SQL>

--Check memory setting

SQL> select a.ksppinm "Parameter",
c.ksppstvl "Instance Value"
from x$ksppi a, x$ksppcv b, x$ksppsv c
where a.indx = b.indx
and a.indx = c.indx
and a.ksppinm in ('_fix_control')
order by 1; 2 3 4 5 6 7

Parameter Instance Value
------------------------------ --------------------
_fix_control 32005394:on

SQL>

 

2. set "_fix_control"='31143146:on' without removing existing settings:

For example:


SQL> alter system set "_fix_control"='31143146:on','32005394:on' scope=both;

System altered.

SQL>

 3.Check the latest settings:

For example:

SQL> select name, value from V$SYSTEM_PARAMETER2 where name like '_fix_control';

NAME VALUE
------------------ --------------------------
_fix_control 31143146:on
_fix_control 32005394:on

SQL> select a.ksppinm "Parameter",
c.ksppstvl "Instance Value"
from x$ksppi a, x$ksppcv b, x$ksppsv c
where a.indx = b.indx
and a.indx = c.indx
and a.ksppinm in ('_fix_control')
order by 1; 2 3 4 5 6 7

Parameter Instance Value
------------------------------ --------------------------
_fix_control 31143146:on, 32005394:on

SQL>


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12798004/viewspace-3172634/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle ACE。ACOUG核心成员,Oracle用户组年轻专家。熟悉Oracle的体系结构,擅长Oracle数据库架构规划、SQL优化、OWI方面性能的优化。曾服务于航天、航空、机车、大型制造行业数据库的维护以及系统开发工作,开发过基于Oracle数据库的大型ERP系统。
  • 博文量
    345
  • 访问量
    2477889