跑批SQL性能异常分析

来源:这里教程网 时间:2026-03-03 19:36:03 作者:

跑批是串行进行的,同时伴随着在线业务,整个跑批过程中只卡在SQL( 6hqva0h4awrxh )执行环节上,相关等待事件为gc current grant 2-way,其他环节及在线业务都不受影响,主机整体资源较为空闲。最后通过重建问题SQL涉及对象的索引解决。

故障时间段的awr、ash性能报告和数据库hanganalyze全局dump信息:

如截图所示并没有出现异常指标及全局的性能问题,种种迹象表明数据库整体负载较为正常。问题只出现在单个

SQL 的执行上。

systemdump  该会话的信息可以看出并没有任何会话堵塞,历史的等待一直为 gc current grant 2-way 。读取的对象是 4 号数据文件 919380 块,其中 4 号数据文件正是 undotbs ,说明会话进程读取数据块前镜像,大量 DML 操作在同一个对象上发生。

说明:

gc current grant 2-way :这个等待事件说明当前实例向主节点申请了一个 current 块,而且这个申请已经被主节点响应,其中并没有出现超时。但是,这个被申请的数据块不包含在任何实例的数据库缓冲区中,它是需要申请实例从数据文件读取出来的,当 current grant 2-way 的等待事件很多,并且消耗了很多等待时间的话,可能的原因如下:

原因 1 :网络带宽

原因 2 :应用程序的角度来讲,导致大量 current/cr grant 2-way 等待事件的原因如下:

2.1 :某些 SQL 语句的执行计划出现了问题

2.2 :数据库缓冲区被设置过小,这导致很多数据被频繁地写入数据文件

2.3 :检查点过于频繁。例如: fast_start_mttr_target 设置的过短

其中原因 1 通过 osw 系统监控被排除, 2.2 2.3 可能性也不大。剩下 2.1 ,我们看一下问题 SQL 语句:

update Bs_account_jnls_tax
  set status = '04'
where status = '00'
  and acc_date = to_date('2024-02-10', 'yyyy-mm-dd')
  and trans_jnls_no in
      (select distinct trans_jnls_no
         from jn_batch_result
        where batch_no in ('75110058', '75110068')
          and acc_date = to_date('2024-02-10', 'yyyy-mm-dd'))

一条简单的 update 语句使用非绑定变量,以下为内存中的执行计划:

由于使用非绑定变量,CBO计算存在误差,实际和看到的执行计划存在不一致的现象。(实际的执行计划需要通过10053单独跟踪验证),这也验证了为什么现场工作人员通过重建索引改变执行计划来解决问题。

总结

通过上述分析判断,最主要的问题还是 SQL 语句本身未使用绑定变量导致执行计划不稳定,执行效率低所导致。

解决方法:

1.  规范开发 SQL 语句编写统一使用绑定变量

2. 评估 Bs_account_jnls_tax 表大小, keep buffer   cache 内存中,或问题 SQL 前先执行 select count(*) from  trans_jnls_no / Bs_account_jnls_tax

3. 如果建议 1 应用短时间内无法变更,再次出现故障时可以尝试从 shared pool 中手动刷出去执行计划重新生成新的,方法如下:

查询对应 sql address hash value

select s.SQL_TEXT, s.ADDRESS || ',' || s.HASH_VALUE from v$sqlarea s where sql_id = '10kq6nc2rfrf0'

exec sys.dbms_shared_pool.purge('0000000141AE1310,91708864','c');

注: 0000000141AE1310,91708864 s.ADDRESS || ',' || s.HASH_VALUE 的值

相关推荐