
从来没去考虑过会关闭。而且大部分都是打开的。实在不巧遇到这个数据库是关闭的
前几天在客户现场排查一个性能问题,发现 Oracle 19c 数据库中 ACS(Adaptive Cursor Sharing,自适应游标共享)居然没有开启。
按照 Oracle 的官方文档,ACS 从 11gR2 开始默认是开启的,但客户的 19c 环境却意外关闭了。这导致了一个典型的性能问题:
自适应游标共享(ACS)是 Oracle 11g 引入的重要特性,用于解决 绑定变量窥探(Bind Peeking)带来的问题。
传统绑定变量窥探的问题:
-- 假设有一个查询
SELECT * FROM orders WHEREstatus = :bind1;
-- 如果第一次执行时 :bind1 = 'ACTIVE'(返回 1000 行)
-- 优化器会生成一个适合返回大量数据的执行计划(比如 FULL SCAN)
-- 后续如果 :bind1 = 'CLOSED'(只返回 10 行)
-- 但 Oracle 仍然使用之前的执行计划,不会重新优化
ACS 的解决方案:
当 ACS 关闭时,Oracle 退回到传统的 绑定变量窥探模式:
可能原因:游标被清除,触发了重新解析。因为我列出了一些可能的原因,然后排除了一些没有发生的情况,那么剩下的是可能性较高的
因为可能的原因包括:
-- 查看共享池使用情况
SELECT * FROM v$sgastat WHEREname = 'free memory'AND pool = 'shared pool';
-- 查看游标失效情况
SELECT sql_id, child_number, executions, loads, invalidations
FROM v$sql
WHERE sql_id = 'your_sql_id';
-- 查看统计信息收集历史
SELECT table_name, last_analyzed, num_rows
FROM dba_tables
WHERE table_name IN ('YOUR_TABLES')
ORDERBY last_analyzed DESC;
当然很明显这个数据库没有重启过。
-- 查看实例启动时间
SELECT startup_time FROM v$instance;
-- 查看是否有人手动刷新共享池
SELECT * FROM dba_audit_trail WHERE obj_name = 'FLUSH SHARED_POOL';
基于以上分析,问题的完整路径应该是:
1. ACS 关闭(隐藏参数 _optimizer_adaptive_cursor_sharing = FALSE)
↓
2. SQL 游标因某种原因被清除(共享池压力/统计信息更新等)
↓
3. 早上 8 点业务高峰,该 SQL 第一次执行
↓
4. 硬解析时碰巧遇到一个"非典型"的绑定变量值
↓
5. 生成了一个次优的执行计划(比如全表扫描)
↓
6. 由于 ACS 关闭,后续所有执行都复用这个次优计划
↓
7. 性能急剧下降,且问题持续存在
采用的方案是:
-- 清除该 SQL 的所有游标
ALTERSYSTEMFLUSHSHARED_POOL; -- 方法1:清空整个共享池(影响大)
这种方案一般来说是不用的。
-- 所以采用下面的
SELECT address, hash_value FROM v$sqlarea WHERE sql_id = 'your_sql_id';
-- 然后逐个清除
这个方案是正确的,因为:
但治本的方案是:
-- 开启 ACS(需要重启)
ALTERSYSTEMSET"_optimizer_adaptive_cursor_sharing" = TRUESCOPE=SPFILE;
ALTERSYSTEMSET"_optimizer_extended_cursor_sharing" = 'UDO'SCOPE=SPFILE;
ALTERSYSTEMSET"_optimizer_extended_cursor_sharing_rel" = 'NONE'SCOPE=SPFILE;
-- 然后重启数据库
基于这次排查经验,我整理了 Oracle 11g 到 19c 所有与性能相关的参数,包括默认值和查询方式。
参数名 | 默认值 | 作用 | 影响 | 查询方式 |
|---|---|---|---|---|
_optimizer_adaptive_cursor_sharing | TRUE (11gR2+) | 启用 ACS | 避免绑定变量导致的次优计划 | SELECT ksppinm, ksppstvl FROM x$ksppi x, x$ksppcv y WHERE x.indx = y.indx AND ksppinm = '_optimizer_adaptive_cursor_sharing'; |
_optimizer_extended_cursor_sharing | UDO (11gR2+) | 控制扩展游标共享行为 | 与 ACS 配合使用 | 同上,替换参数名 |
_optimizer_extended_cursor_sharing_rel | NONE (11gR2+) | 关联查询的扩展游标共享 | 影响复杂查询稳定性 | 同上,替换参数名 |
注意:这三个参数都是隐藏参数,修改需要重启实例。
参数名 | 默认值 | 作用 | 影响 | 查询方式 |
|---|---|---|---|---|
_optimizer_adaptive_features | TRUE (12cR1+) | 启用自适应优化器 | 运行时调整执行策略 | 隐藏参数查询 |
optimizer_adaptive_plans | TRUE (12cR2+) | 启用自适应执行计划 | 改善复杂查询,增加 CPU 开销 | SHOW PARAMETER optimizer_adaptive_plans |
optimizer_adaptive_statistics | FALSE (12cR2+) | 启用自适应统计信息 | 动态收集统计信息 | SHOW PARAMETER optimizer_adaptive_statistics |
参数名 | 默认值 | 作用 | 影响 | 查询方式 |
|---|---|---|---|---|
_optimizer_use_feedback | TRUE (11gR2+) | 启用基数反馈 | 自动纠正错误基数估算 | 隐藏参数查询 |
_optimizer_cardinality_feedback | TRUE (12c+) | 基数反馈详细行为 | 与上一参数配合 | 隐藏参数查询 |
参数名 | 默认值 | 作用 | 影响 | 查询方式 |
|---|---|---|---|---|
optimizer_dynamic_sampling | 2 (11g+) | 动态采样级别 (0-11) | 改善统计信息缺失表的查询 | SHOW PARAMETER optimizer_dynamic_sampling |
参数名 | 默认值 | 作用 | 影响 | 查询方式 |
|---|---|---|---|---|
memory_target | 0 (需手动设) | 启用 AMM | 简化内存管理,但可能不稳定 | SHOW PARAMETER memory_target |
memory_max_target | 0 | AMM 最大限制 | 限制最大内存使用 | SHOW PARAMETER memory_max_target |
sga_target | 0 (需手动设) | 启用 ASMM | 自动调整 SGA 组件 | SHOW PARAMETER sga_target |
pga_aggregate_target | 10M 或 SGA 20% | PGA 总大小 | 影响排序、哈希操作 | SHOW PARAMETER pga_aggregate_target |
参数名 | 默认值 | 作用 | 影响 | 查询方式 |
|---|---|---|---|---|
parallel_degree_policy | MANUAL (11gR2+) | 并行度策略 | AUTO/ADAPTIVE 自动决定并行度 | SHOW PARAMETER parallel_degree_policy |
parallel_degree_limit | CPU (11gR2+) | 并行度最大值 | 防止过度并行 | SHOW PARAMETER parallel_degree_limit |
parallel_min_time_threshold | 10 (秒) | 并行最小时间阈值 | 避免短查询并行 | SHOW PARAMETER parallel_min_time_threshold |
参数名 | 默认值 | 作用 | 影响 | 查询方式 |
|---|---|---|---|---|
result_cache_mode | MANUAL (11g+) | 结果缓存模式 | AUTO 自动决定是否缓存 | SHOW PARAMETER result_cache_mode |
result_cache_max_size | 0 或 sga*0.25% | 缓存最大大小 | 限制内存使用 | SHOW PARAMETER result_cache_max_size |
result_cache_max_result | 5 (%) | 单结果最大占比 | 防止单个结果占满缓存 | SHOW PARAMETER result_cache_max_result |
参数名 | 默认值 | 作用 | 影响 | 查询方式 |
|---|---|---|---|---|
optimizer_use_sql_plan_baselines | TRUE (11g+) | 启用 SQL 计划基线 | 防止执行计划退化 | SHOW PARAMETER optimizer_use_sql_plan_baselines |
optimizer_capture_sql_plan_baselines | FALSE | 自动捕获基线 | 自动维护计划稳定性 | SHOW PARAMETER optimizer_capture_sql_plan_baselines |
参数名 | 默认值 | 作用 | 影响 | 查询方式 |
|---|---|---|---|---|
optimizer_use_pending_statistics | FALSE (11g+) | 使用待定统计信息 | 验证统计信息后再发布 | SHOW PARAMETER optimizer_use_pending_statistics |
_optimizer_gather_stats_on_load | TRUE (11g+) | 加载时自动收集统计 | 保持统计信息新鲜 | 隐藏参数查询 |
参数名 | 默认值 | 作用 | 影响 | 查询方式 |
|---|---|---|---|---|
_optimizer_cost_based_transformation | TRUE | 基于成本的查询转换 | 改善复杂查询优化 | 隐藏参数查询 |
_optimizer_null_aware_antijoin | TRUE (11g+) | NULL 感知反连接 | 改善 NOT IN 性能 | 隐藏参数查询 |
_optimizer_use_histograms | TRUE | 使用直方图 | 改善数据倾斜列估算 | 隐藏参数查询 |
_optimizer_system_stats_usage | TRUE | 使用系统统计信息 | 基于硬件成本的优化 | 隐藏参数查询 |
SELECT ksppinm AS parameter_name,
ksppstvl AS current_value,
ksppdesc AS description
FROM x$ksppi x, x$ksppcv y
WHERE x.indx = y.indx
AND ksppinm IN (
'_optimizer_adaptive_cursor_sharing',
'_optimizer_extended_cursor_sharing',
'_optimizer_extended_cursor_sharing_rel'
);
SELECTname, value, description
FROM v$parameter
WHEREnameLIKE'optimizer%'
ORDERBYname;
-- 查询所有 _optimizer 开头的隐藏参数
SELECT ksppinm AS parameter_name,
ksppstvl AS current_value,
ksppdesc AS description
FROM x$ksppi x, x$ksppcv y
WHERE x.indx = y.indx
AND ksppinm LIKE'_optimizer%'
ORDERBY ksppinm;
ACS 相关参数:保持默认值(开启)
-- 验证 ACS 是否开启
SELECT ksppinm, ksppstvl
FROM x$ksppi x, x$ksppcv y
WHERE x.indx = y.indx
AND ksppinm = '_optimizer_adaptive_cursor_sharing';
自适应优化器:12cR2+ 建议开启
ALTERSYSTEMSET optimizer_adaptive_plans = TRUESCOPE=BOTH;
SQL 计划管理:建议开启基线保护
ALTERSYSTEMSET optimizer_use_sql_plan_baselines = TRUESCOPE=BOTH;
当遇到执行计划突变问题时:
ALTER SYSTEM FLUSH SHARED_POOL(谨慎使用)这次排查揭示了一个重要问题:Oracle 19c 虽然默认开启 ACS,但在某些情况下安装时候特意去关闭。 自己想当然觉得这个是默认的就没去关注。也许我也没分析对,有人如果有更好的分析可以告诉我。