从事IT数据库行业,记录日常工作中数据库知识及一些生产故障案例,不废话。如有不对请指正,欢迎关注小编:
微信:xh870545795 优快云:dba_notes
公众号:咖啡逗不逗
一、问题背景
客户一套生产rac集群,版本为11.2.0.4,无补丁,反馈有性能问题,应用查询缓慢,数据库hang住,远程接入排查处理。
二、分析过程
1.排查数据库告警日志
从12:17之后TNS类错误开始出现,主要为操作超时。因此判断数据库可能存在阻塞。
2.排查阻塞
通过关联查询,查询语句如下,找到阻塞的源头:
select * from (select a.inst_id, a.sid, a.serial#, a.sql_id, a.event, a.status, connect_by_isleaf as isleaf, sys_connect_by_path(a.SID||'@'||a.inst_id, ' <- ') tree, level as tree_level from gv$session a start with a.blocking_session is not null connect by (a.sid||'@'||a.inst_id) = prior (a.blocking_session||'@'||a.blocking_instance)) where isleaf = 1 order by tree_level asc;
可以看到相关的SQL语句:
仅从查询的SQL语句很难断定这个查询语句就是阻塞产生的源头,通过DBA和开发人员确认,该SQL语句是存储过程P_GETBATSEQ的一部分:
查询语句的主要任务是获取序列,然后根据判断条件再进行insert或者update操作。
3.排查AWR
通过AWR报告也证明 了这一点:
同时,通过AWR可以看到SegmentsbyRowLockWaits情况如下:
通过以上现象判断为阻塞导致数据库异常,更改了相关存过的语句,创建序列create SEQUENCE代替存过获取序列的方式,并kill相应阻塞问题解决,本以为问题到此就结束了,但是第二天早上5点现象又出现,客户通过重启数据库,业务恢复。于是赶赴现场继续排查。
4.现场排查
早上出现的原因不是存过里面序列表,而是别的语句,因此感觉这个问题和存过序列表关系不大,继续分析awr如下:
发现gc freelist这个等待事件很高,平均达到195ms,查询问题时段的等待事件,按分钟查询:
select to_char(sample_time,'hh24:mi'),event, count(1)from dba_hist_active_sess_history awhere a.sample_time>=to_date('20240920 05:30:00','yyyymmdd hh24:mi:ss') and a.sample_time<=to_date('20240920 05:40:00','yyyymmdd hh24:mi:ss')and event is not null group by to_char(sample_time,'hh24:mi'),eventhaving count(1)>2 order by 1;
发现gc freelist等待事件随着时间不断增长,查看数据库trace:
显示在前一天晚上23点已经出现了gc freelist,通过语句查询如下:
因此怀疑和gc freelist等待事件有关,通过mos查询,发现官方有相关说明:
Database Hangs with High "gc freelist" wait (Doc ID 2055409.1)
大概的意思就是,产生gc freelist的原因是锁没有足够快的被释放,这是一个代码缺陷。也就是说是一个BUG,它会导致锁的关闭速度不够快,从而导致 gc freelist等待,该问题不仅会影响 Oracle Database 12.1.0.2,还会影响 Oracle Database 11.2.0.3 和 11.2.0.4。mos解释如下:
官方博客也有类似案例说明:https://mikedietrichde.com/2016/03/22/gc-freelist-session-waits-causing-slowness-and-hangs/
官方给出的解决方案如下两种:
(1)应用18628388补丁
(2)修改_gc_element_percent参数
三.处理过程
根据官方建议当晚进行了这个小补丁的升级,以下为测试环境上的升级过程,没有问题才上生产操作(打psu客户觉得风险太大,因此根据官方建议升级此补丁)
1.备份DB ORACLE_HOME(两节点)
[root@xhdb01]# cd /u01/app/oracle/product/11.2.0[root@xhdb01]# tar -pcvzf db_0921.tar.gz db
2.上传补丁及opatch(两节点)
3.赋权限(两节点)
[root@xhdb01:]# chown oracle: /patch/ -R
4.oracle用户替换opatch(两节点)
[root@xhdb01:]# su - oracle[oracle@xhdb01:]$cd $ORACLE_HOME[oracle@xhdb01:]$mv OPatch/ OPatch.bak
解压新的opatch到ORACLE_HOME:
[oracle@xhdb01:/patch]$ unzip p6880880_112000_Linux-x86-64.zip -d $ORACLE_HOME
5.节点1打补丁
(1)解压补丁包
[oracle@xhdb01:]$ unzip p18628388_112040_Linux-x86-64.zip
(2)关闭节点1数据库
SQL> shutdown immediate;
(3)节点1打补丁
[oracle@xhdb01:]$ cd 18628388/[oracle@xhdb01:]$ /u01/app/oracle/product/11.2.0/db/OPatch/opatch apply
检查补丁应用情况
[oracle@xhdb01:/patch/18628388]$ /u01/app/oracle/product/11.2.0/db/OPatch/opatch lsinventory
(4)启动节点1数据库
SQL> startup
6.节点2打补丁
(1)解压补丁包
[oracle@xhdb02:]$ unzip p18628388_112040_Linux-x86-64.zip
(2)关闭节点2数据库
SQL> shutdown immediate;
(3)节点2打补丁
[oracle@xhdb02:]$ cd 18628388/[oracle@xhdb02:]$ /u01/app/oracle/product/11.2.0/db/OPatch/opatch apply
检查补丁应用情况
[oracle@xhdb02:/patch/18628388]$ /u01/app/oracle/product/11.2.0/db/OPatch/opatch lsinventory
(4)启动节点2数据库
SQL> startup
7.回退方案
(1)补丁回退
[oracle@xhdb01:/patch/18628388]$ opatch rollback -id 18628388
(2)操作前备份软件回退
通过补丁升级前所备份DB的ORACLE_HOME解压后并替换现有DB的ORACLE_HOME。
[root@xhdb01]# tar -zxvf db_0921.tar.gz
今天就分享到这里,如有不对请指正,感谢关注!