ash内存收集默认开启,但需诊断包许可支持;_ash_enable为隐式参数,禁用需修改spfile并重启;ash_size受shared_pool_size和_kghdsidx_count限制,实际分配需查v$sgastat。
ash内存收集默认是否开启?_ash_enable 是关键开关
Oracle 10g起ASH(Active Session History)默认启用,但前提是数据库启用了诊断包(Diagnostic Pack)许可——没买这个License,V$ACTIVE_SESSION_HISTORY 视图会为空,哪怕_ash_enable 显示为TRUE。_ash_enable 是隐式参数,不能直接用ALTER SYSTEM SET 修改,只能通过ALTER SYSTEM SET "_ash_enable"=FALSE SCOPE=SPFILE + 重启生效。
- 生产库别轻易关它,AWR快照、ADDM、实时SQL监控都依赖ASH数据
- 关闭后
V$SESSION_WAIT和V$SESSION_EVENT不会受影响,但“过去1小时谁在等什么”这类分析就断了 - 检查当前状态:执行
SELECT ksppinm, ksppstvl FROM x$ksppi a, x$ksppcv b WHERE a.indx = b.indx AND ksppinm = '_ash_enable'
ash_size不是你想调多大就多大:受shared_pool_size和_kghdsidx_count制约
ash_size 控制ASH缓冲区总大小(单位字节),但它不是独立内存池,而是从shared pool里切一块出来。所以:
- 如果
shared_pool_size太小(比如256M),设ash_size=512M会被Oracle静默截断到可用上限 - 实际分配量还受
_kghdsidx_count影响(默认8),它决定shared pool的子池数量,每个子池都要预留ASH空间,碎片化严重时可能分配失败 - 查看真实分配值:
SELECT * FROM v$sgastat WHERE pool = 'shared pool' AND name = 'ASH buffers' - 建议值:OLTP库一般
100M~200M够用;高并发短会话场景可设300M,但必须同步确认shared pool有余量
历史保留时间不只看ash_size:采样频率+活动会话数才是硬约束
ASH每秒采样一次活跃会话(ACTIVE状态),每条记录约1KB。理论保留时长 = ash_size / (活动会话数 × 1KB × 1次/秒)。
- 100个活跃会话 → 每秒写100KB →
ash_size=100M只能撑约17分钟 - 实际中因采样抖动、空闲会话过滤、后台进程占用,往往只有理论值的60%~80%
- 不要指望调大
ash_size就能保留24小时——除非你把所有非活跃会话全干掉,或者接受极低采样率(Oracle不支持调低采样频率) - 长期分析靠AWR:ASH是“热数据”,AWR是“冷归档”,两者互补,不是替代关系
查不到历史ASH数据?先盯住V$ACTIVE_SESSION_HISTORY和V$ASH_INFO
V$ACTIVE_SESSION_HISTORY 只返回最近约1小时(或ash_size满后循环覆盖)的数据;想确认是否真丢了,别只查这个视图。
- 看实时写入是否正常:
SELECT count(*) FROM v$active_session_history WHERE sample_time > sysdate - 1/1440(过去1分钟应有几十到几百行) - 查ASH内部统计:
SELECT * FROM v$ash_info,重点关注ASH BUFFERS WRITTEN(累计写入量)和ASH BUFFER DROPPED(被丢弃数,>0说明buffer不够) - 如果
ASH BUFFER DROPPED持续增长,说明ash_size确实小了,或者shared pool争用严重(查v$sgastat里free memory是否长期低于10MB)
实际调优时,ash_size 和 shared pool 的配比、License状态、采样密度这三者咬得很死,改一个得验另外两个。很多人调完发现没效果,问题常出在没查v$ash_info里的丢弃计数。










