awr查不到绑定变量值主因是采样机制限制,非所有变量均被采集;需确认dba_hist_sqlbind中是否存在记录、检查was_captured字段、优先用v$sql_bind_capture查实时值,并注意value_anydata类型匹配与last_captured时间非执行时间。

AWR里查不到绑定变量值?先确认是否被采样到
DBA_HIST_SQLBIND 不是“所有绑定变量的全量日志”,它只保存被AWR采样机制捕获到的变量。常见空结果不是SQL没传绑定,而是根本没被捕获——比如INSERT语句的VALUES部分在10g–12c默认不捕获;变量长度超过2000字节被截断;或该次执行恰好落在两次采样间隔(默认900秒)之外。
实操建议:
- 用
SELECT COUNT(*) FROM dba_hist_sqlbind WHERE sql_id = 'xxx' AND snap_id BETWEEN 1000 AND 1010确认该SQL在目标快照区间是否有记录,别只查单个snap_id - 检查
WAS_CAPTURED = 'YES'字段,它比VALUE_STRING是否为空更可靠 - 对INSERT/UPDATE语句,优先查
v$sql_bind_capture(实时共享池),而非dba_hist_sqlbind(历史采样)
VALUE_ANYDATA解包失败?类型匹配必须手动做
VALUE_ANYDATA 是Oracle内部序列化格式,不能直接TO_CHAR()强转。错用ANYDATA.ACCESS_NUMBER()解VARCHAR2会报ORA-22370,而用ACCESS_VARCHAR2()解NUMBER只会返回NULL——不报错但结果丢失。
实操建议:
- 先用
ANYDATA.GETTYPENAME(VALUE_ANYDATA)拿真实类型名(如'SYS.VARCHAR2'、'SYS.DATE'),别信DATATYPE_STRING字段的描述性文本 - DATE和TIMESTAMP都可能映射为
DATATYPE_STRING = 'DATE',但实际值可能是SYS.TIMESTAMP WITH TIME ZONE,强行ACCESS_DATE()会失败 - 稳妥写法是CASE分支:
CASE WHEN ANYDATA.GETTYPENAME(VALUE_ANYDATA) = 'SYS.VARCHAR2' THEN ANYDATA.ACCESS_VARCHAR2(VALUE_ANYDATA) ... END
绑定变量过多导致AWR快照失败?重点盯wrh$_sql_bind_metadata
当MMON进程报ORA-12751(cpu time or run time policy violation)且快照卡在85%,大概率是wrh$_sql_bind_metadata表处理超时——该表存绑定元数据,绑定变量越多、越长,扫描越慢。Oracle内部对单条SQL的绑定采集有隐式限制,但高并发下仍可能堆积。
实操建议:
- 临时禁用绑定采集:
ALTER SYSTEM SET "_awr_disabled_flush_tables" = 'wrh$_sql_bind_metadata';(需重启MMON生效) - 清空共享池常能缓解:
ALTER SYSTEM FLUSH SHARED_POOL;,但只是治标;长期需优化应用,减少无意义绑定(如INSERT中大量NULL占位) - 避免全扫
dba_hist_sqlbind:务必加dbid、sql_id、snap_id三重过滤,否则I/O和内存压力会拖垮查询本身
对比不同快照的绑定值?注意last_captured不是执行时间
LAST_CAPTURED 是AWR采样时间点,不是SQL实际执行时间。同一SQL在多个快照中出现不同绑定值,不代表它在不同时段执行了不同参数——可能只是采样时机不同,或应用在持续重用同一游标。
实操建议:
- 不要用
last_captured推断业务行为时间线,它只反映采样时刻;真要定位某次慢查询,得结合ASH的sql_exec_start和sql_id反查对应快照 - 发现同一
sql_id在不同快照中value_string差异大,优先排查是否用了/*+ BIND_AWARE */或自适应游标共享(ACS)触发了不同执行路径 - 对高频SQL,
dba_hist_sqlbind可能被截断(默认每SQL最多存1000行),查不到旧值不等于没发生过
v$sql_bind_capture、dba_hist_sqlbind,还是直接抓ASH。











