首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >警示:一个update语句引起大量gc等待和业务卡顿

警示:一个update语句引起大量gc等待和业务卡顿

作者头像
数据和云
发布于 2020-07-15 09:44:30
发布于 2020-07-15 09:44:30
78300
代码可运行
举报
文章被收录于专栏:数据和云数据和云
运行总次数:0
代码可运行

墨墨导读:业务卡顿异常,有几个 insert into 语句的gc等待比较严重,发生业务超时,本文分析了超时原因并详述整个处理过程,希望对大家有帮助。

1. 故障现象

客户报2020年7月9号,8点30分左右业务卡顿异常,有几个 insert into 语句的gc等待比较严重,发生业务超时,需要紧急分析一下超时原因,并给出处理建议。

2. AWR分析

由于是业务卡顿分析,可以让客户配合出各节点实例的awr报告辅助分析,另一方面同时进行分析ASH信息:

可以看到gc等待排第一位,等待次数异常高。

可以看到gc等待主要是由3个insert into语句产生的。

3. 诊断分析及建议

首先先备份ASH表,避免数据被刷出内存:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from gv$active_session_history
 where sample_time >=
       to_date('2020-07-09 08:00:00', 'yyyy-mm-dd hh24:mi:ss')
   and sample_time <
       to_date('2020-07-09 10:00:00', 'yyyy-mm-dd hh24:mi:ss')

其次查询各实例按分为统计单位的等待次数趋势情况:

可以发现实例1并没有等待暴增的情况,而实例2在8:30时等待暴示,进一步查询实例2等待次数变化情况:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  from gv$active_session_history
 where sample_time >=
       to_date('2020-07-09 08:00:00', 'yyyy-mm-dd hh24:mi:ss')
   and sample_time <
       to_date('2020-07-09 10:00:00', 'yyyy-mm-dd hh24:mi:ss')
   and event is not null
   and inst_id=1
 group by event
 order by 2 desc;

可以看到确实是节点2的GC等待很严重。

进一步查询gc等待严重的sql语句是哪些:

可以看到这三个gc等待严重的SQL语句都是insert into语句,且是插入同一个表。这里和AWR的分析相吻合,进一步查询gc使用块类型占比,考虑如果被用于撤销块比例过多,则应用实例划分可以大大降低GC传输。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  trunc(data_requests / decode(tot_req,0,1), 2) * 100 data_per,  --data blocks
       trunc(undo_requests / decode(tot_req,0,1), 2) * 100 undo_per,  --undo blocks
       trunc(tx_requests / decode(tot_req,0,1), 2) * 100 tx_per,      --undo header blocks
       trunc(other_requests / decode(tot_req,0,1), 2) * 100 other_per --other blocks
  from (select inst_id,
               cr_requests + current_requests tot_req,
               data_requests,
               undo_requests,
               tx_requests,
               other_requests
          from gv$cr_block_server)
 order by inst_id;

这里除了看到数据块的CR块GC传输比较多,也可以看到undo header的cr块传输占比也很大。进一步查询gc buffer busy acquire等待按块类型分类情况:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 (select *
    from (select /*+ materialize */
           inst_id,
           event,
           current_obj#,
           current_file#,
           current_block#,
           count(*) cnt
            from gv$active_session_history
           where event = 'gc buffer busy acquire'
           group by inst_id,
                    event,
                    current_obj#,
                    current_file#,
                    current_block#
          having count(*) > 5)
   where rownum < 101)
select *
  from (select inst_id,
               owner,
               object_name,
               object_type,
               current_file#,
               current_block#,
               cnt
          from ash_gc a, dba_objects o
         where (a.current_obj# = o.object_id(+))
           and a.current_obj# >= 1
        union
        select inst_id,
               '',
               '',
               'Undo Header/Undo block',
               current_file#,
               current_block#,
               cnt
          from ash_gc a
         where a.current_obj# = 0
        union
        select inst_id,
               '',
               '',
               'Undo Block',
               current_file#,
               current_block#,
               cnt
          from ash_gc a
         where a.current_obj# = -1)
 order by 7 desc

可以看到Undo Header/Undo block的统计次数最大,最严重的GC等待来自undo上的数据块,验证了前面cr块的gc传输很大的情况。由于都是同一个表的gc传输,这时客户开发反馈,昨晚有业务处理

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 set a.subpayway ='05'
  where exists (select 1 from t1_20200708 b where a.bizfeedetid = a.bizfeedetid);

但中间杀了没提交,写入表慢是否跟这个有关? 根据这个信息,怀疑是这个UPDATE语句的表数据量很大,执行非常慢才去杀掉的,客户回复可能是没有写好条件,这个SQL等于是更新了整张表,确实是中止了,进行异常回滚而没有正常提交。从SQL写法上(a.bizfeedetid = a.bizfeedetid)也可以看到恒等的错误,查看这个表数据量:

这个表不是分区表,数据量达到6亿多条,update全表根本无法完成。 分析gc buffer busy acquire等待事件:

这里可以知道gc buffer busy acquire等待需等待lgwr刷新未提交的变更到日志中,也就需要undo的回滚和一致性要求,根据以往的经验,如果如果lgwr写入慢,则会进一步加重在gc的等待,进一步查看lgwr 的 trace,发现写抖动严重:

节点1、节点2,也就是实例1、实例2的lgwr写入都存在写入延迟的问题,lgwr写入抖动很严重,2KB都要写516ms,lgwr写入慢,如果碰上大量的gc块获取,就会产生大量的gc等待,这里lgwr刷新需求和lgwr写入慢相应验证插入业务卡顿的故障现象。

继续查log file parallel write直方图:

同样验证log写入有比较严重的抖动现象。

可通过v$fast_start_transactions视图查看正在回滚的事务:

根据XID事务ID已经找不到对应事务了,只有之前完成的回滚。

查询到这条update只在节点1执行,且最后一次执行时间是在09:59分,此时已经11点了,没有查到回滚事务信息,说明已经完成了事务回滚,故障已自动恢复。这里客户反馈库这时latch: cache buffers chains等待严重,查询此时的等待链信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
with ash as
 (select /*+ materialize*/
   *
    from gv$active_session_history t
   where sample_time >=
         to_date('2020-07-09 11:00:00', 'yyyy-mm-dd hh24:mi:ss')
     and sample_time <
         to_date('2020-07-09 12:00:00', 'yyyy-mm-dd hh24:mi:ss')),
chains as
 (select inst_id,
         blocking_session blocking_sid,
         blocking_session_serial#  blocking_serial,
         session_id,
         session_serial# session_serial,
         level lvl,
         sys_connect_by_path(inst_id||' '||session_id || ',' || session_serial# || ' ' ||
                             sql_id || ' ' || event,
                             ' <-by ') path,
         connect_by_isleaf isleaf
    from ash
   start with event in ('latch: cache buffers chains')
  connect by nocycle(prior blocking_session = session_id
                 and prior blocking_session_serial# = session_serial#
                 and prior sample_id = sample_id))
select inst_id,
       blocking_sid,
       blocking_serial,
       lpad(round(ratio_to_report(count(*)) over() * 100) || '%', 5, ' ') "%This",
       count(*) ash_time,
       path
  from chains
 where isleaf = 1
 group by inst_id,blocking_sid,blocking_serial, path
 order by inst_id,ash_time desc;

依然是之前一个那个没有分区的6亿条记录表的一条insert语句,只是等待事件由gc变成cbc等待,根据以往处理经验,CBC的等待需要考虑BUFFER不够和访问热点的问题,需要从表结构、表参数、索引设计、索引参数等考虑优化。

客户反馈这个表是一些中间数据,分区标识不明显,所以一直没有进行分区,且对查询要求比较高,还会和三个同等大小的表关联。

针对这种情况,我们给出建议是创建成全局HASH分区表可能较合适的,索引也相应创建成分区索引,需要根据业务再讨论设计。可以先设置pctfree参数缓解CBC。

综合以上的分析,可以确认本次故障是由于开发一条update语句条件错误导致大量的undo事务回滚,使在另一实例上的相同表的几个业务上insert into语句产生大量的gc buffer busy acquire等待,加上lgwr写入抖动加剧了等待时长,最终引起了前台业务卡顿。

4. 故障总结

一个update语句写法错误就导致了整个业务系统的务卡顿,说明对大表的DML/DDL操作需要更加慎重,大表操作更加容易导致故障发生,如果语句错误需要及时发现,更早时间介入处理,以避免长时间造成的业务卡顿。

针对本次故障,给予以下几个建议:

  1. 应用上要尽量避免这样的操作异常造成的大量回滚,针对大表的DML/DDL操作需要更加慎重。
  2. 为尽量避免GC等待,可以考虑进行应用划分,某个业务功能限制在一个节点中执行。
  3. log file parallel write日志写入有严重的延迟,需要存储厂商配合进一步分析。
  4. 当前大表建议改造为全局HASH分区表可能更合适,索引也相应创建成分区索引,需要根据业务再讨论设计。可以先设置pctfree参数缓解CBC。

墨天轮原文链接:https://www.modb.pro/db/27542

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据和云 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
经验之谈:内存问题造成数据库性能异常怎么破?
导读:在使用数据库的过程中,内存不足常常会引起数据库异常。但是内存不足,又会为数据库带来哪些具体的影响呢?本次,我们将通过某客户现场数据库在某个时段内性能严重下降的案例来展示由于主机内存不足而造成数据库日志写入卡顿的问题分析过程。通过本案例,我们也可以对相关问题的分析方法及解决建议有一些深入的了解。
数据和云
2020/03/11
1.2K0
经验之谈:内存问题造成数据库性能异常怎么破?
####### Scripts Summary #######
Scripts Summary Version: 1.0.1 issueDate: 2017-11-11 modifiedDate: 2017-11-28
Alfred Zhao
2019/05/24
6010
探索ASH 第一篇
老是在用ASH,对它的依赖感觉已经大于AWR,昨天心血来潮,想看看ash视图里面是怎么样的,过程也算曲折,不过也算抛砖引玉。 先看看v$active_session_history的情况。 -->是个同义词 SQL> select owner,object_name,object_type from dba_objects where object_name='V$ACTIVE_SESSION_HISTORY'; OWNER OBJECT_NAME
jeanron100
2018/03/13
1.1K0
如何通过 dba_hist_active_sess_history 分析数据库历史性能问题
如何通过 dba_hist_active_sess_history 分析数据库历史性能问题背景在很多情况下,当数据库发生性能问题的时候,我们并没有机会来收集足够的诊断信息,比如system state dump或者hang analyze,甚至问题发生的时候DBA根本不在场。这给我们诊断问题带来很大的困难。那么在这种情况下,我们是否能在事后收集一些信息来分析问题的原因呢?在Oracle 10G或者更高版本上,答案是肯定的。本文我们将介绍一种通过dba_hist_active_sess_history的数据来
lemotree
2022/06/21
2.7K1
Oracle案例:一次gc buffer busy acquire诊断
本案例来自某客户两节点rac的一次生产故障,现象是大面积的gc buffer busy acquire导致业务瘫痪。 首先查看1节点AWR头部信息和load profile: 1节点AWR 得到的关键信息点: 对于LCPU 256的系统,AAS=13379.42/59.91=223,说明系统非常繁忙或者遇到了异常等待。 sessions异常增长好几倍,DB CPU/DB Time占比非常低,说明是遇到了异常等待。 其余指标都还算正常。 既然是遇到异常等待,那么就看看top event部分: 1节点AWR
数据和云
2022/03/04
1.7K0
DBA命令速查6: 临时表空间( Temporary Tablespace)的相关确认SQL
编者按:留存一下供自己需要时查找。 【免责声明】本号文章仅代表个人观点,与任何公司无关,仅供参考。 编辑|SQL和数据库技术(ID:SQLplusDB) 临时表空间表空间信息 select * from dba_temp_free_space; 临时表空间的使用量 SELECT d.tablespace_name "Name" , NVL(a.bytes / 1024 / 1024, 0) "Size(MB)", NVL(t.bytes, 0) / 1024 / 1024 "U
SQLplusDB
2022/08/22
8090
资源下载丨Oracle优化工程师常用的34个脚本
墨墨导读:本文分享Oracle驻场工程师常用的脚本,基本上包含了日常监控、维护、故障定位及处理、SQL性能优化大部分场景,有了这些脚本会让你的工作变得更轻松,文末附下载链接。
数据和云
2021/03/09
7550
DBA常用SQL语句(6)- ​日常管理
由于 v$active_session_history 和 dba_hist_active_sess_history 的数据来源于 awr 和 ash 采样,记录并不完全,故查询结果并不准确。
Yunjie Ge
2022/04/23
5790
实战演练:洞若观火--治堵之道在清源
堵塞往往是一件可怕的事情,交通堵塞让人心烦意乱,水道堵塞城市就会臭气冲天,言路堵塞则是非难辨。数据库出现会话堵塞,则很可能造成系统业务中断,这对于 DBA 来说,是一个非常大的考验。
数据和云
2018/07/27
3950
实战演练:洞若观火--治堵之道在清源
记录一则enq: TX - row lock contention的分析过程
故障描述:与客户沟通,初步确认故障范围大概是在上午的8:30-10:30之间,反应故障现象是Tomcat的连接数满导致应用无法连接,数据库alert中无明显报错,需要协助排查原因。 1.导入包含故障时刻的数据 2.创建m_ash表,明确故障时刻 3.确定异常时刻的top n event 4.确定最终的top holder 5.总结 6.reference 1.导入包含故障时刻的数据 为了便于后续分析,我向客户索要了从昨天下午13:00到今天18:00的awrdump,导入到自己的实验环境进行分析。 生产环境
Alfred Zhao
2018/05/11
1.6K0
Oracle DBA的SQL编写技能提升宝典(含SQL资源)
背景:要迁移数据库,需要创建与源库相同的表空间,大小与源库相同。由于个别表空间较大,手工添加可能需要写很多的脚本,于是同事通过PL/SQL解决了问题。
数据和云
2021/10/13
1.2K0
Oracle DBA的SQL编写技能提升宝典(含SQL资源)
3个最常见案例详解DBA日常维护
导读:DBA的大部分工作都是围绕着对数据库的维护而展开的,常规的日常维护更是占了绝大多数。本节将围绕日常维护中最常见的三个案例展开讲解,与大家分享排查此类问题的思路。
IT阅读排行榜
2021/08/05
1K0
3个最常见案例详解DBA日常维护
浏览器搞定一切的云时代:在线Oracle数据库运行环境+可访问Linux主机环境
现在有很多的各种数据库SQL在线运行网站,但是提供一个包含安装了数据库的在线的Linux环境的好像并不多。
SQLplusDB
2022/08/22
1.4K0
浏览器搞定一切的云时代:在线Oracle数据库运行环境+可访问Linux主机环境
【DB笔试面试823】在Oracle中,如何查看过去某一段时间数据库系统的会话是否有问题?
【DB笔试面试823】在Oracle中,如何查看过去某一段时间数据库系统的会话是否有问题?
AiDBA宝典
2020/06/17
2.3K0
另辟蹊径第二弹,时间规律里的秘密
墨墨导读:在上个月的数据技术嘉年华里,我做了名为《另辟蹊径:从其他角度去解决数据库问题》的案例分享,讲述了通过时间规律来解决系统故障的思路。结果,这两天又出了类似的案例。和大家分享一下解决这个新问题的过程。
数据和云
2021/02/08
4720
运维,诊断,健康检查,优化定制工具ora使用说明
使用工具的目的是为了提高工作效率, 先有思路和方法,然后再借助工具,方能达到事半功倍的效果.
老虎刘
2022/06/27
1.5K0
SQL工具集-查询会话等待
OLTP系统中,经常碰到的一种场景,就是某个操作卡住了,再从日志定位,很可能就看到是在执行某个增删改的数据库操作的时候出现hang的问题。
bisal
2020/08/25
8430
SQL工具集-查询会话等待
【DB笔试面试653】在Oracle中,请列举一次等待事件的处理案例。
对于这道面试题而言,每个人遇到的情况不一样,答案也就不一样。只需要列举自己曾经碰到的情况,然后讲述明白即可,下面作者给出自己曾经碰到的一个案例及其处理过程。
AiDBA宝典
2019/09/29
9920
【DB笔试面试653】在Oracle中,请列举一次等待事件的处理案例。
快速找到OEACLE的性能问题
对于传统应用系统,一旦系统性能测试达标上线后,后续出现性能恶化除了业务徒增之外,十有八九都是数据库惹的祸。通过快速的业务量比对排除异常后,重点的问题排查就要放到数据库性能上。今天我们就ORACLE数据库性能恶化的定位处理方法进行总结,用此方法可快速的找到故障原因。 数据库之所以出现性能恶化,其实就是在数据库所需要的CPU、内存、IO、网络等方面的现有的资源,无法满足当前系统所要消耗的资源。既然已经排除了业务量的徒增,也就间接说明这种消耗是非正常的消耗,我们把非正常消耗资源的业务逻辑找出来,也就间接的找到了性
企鹅号小编
2018/01/11
8600
快速找到OEACLE的性能问题
案例解读:利用12c渐进式DASH分析"ON CPU"
墨墨导读:本文来自墨天轮读者“Anbob”供稿,分享利用12c渐进式DASH分析"ON CPU"的过程。
数据和云
2021/03/11
6040
推荐阅读
相关推荐
经验之谈:内存问题造成数据库性能异常怎么破?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验