生产库故障分析(主外键和DML性能分析)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 原创 转载请注明出处 (我的学习笔记)    公司生产库2009年06月18日,出现批处理(JOB)阻塞了大量的用户操作,具体表现就是大量的表备锁做,并且CPU资源消耗达到了60%,让整个系统变慢,此时间长达30分钟。

原创 转载请注明出处

(我的学习笔记)   

公司生产库20090618,出现批处理(JOB)阻塞了大量的用户操作,具体表现就是大量的表备锁做,并且CPU资源消耗达到了60%,让整个系统变慢,此时间长达30分钟。

出现问题后,我首先查看了系统使用有大事物的存在:

select username,opname,

round(((totalwork-sofar)/totalwork),4)*100 "pct_remaining"

from V$session_Longops

WHERE TIME_REMAINING >0;

看到有大的的FULL SCAN 也就是全表扫描存在,当然这样也看不出来问题的所在,然后进行了4点到5点的AWRRPT,报告截图如下

WORKLOAD REPOSITORY report for

DB Name

DB Id

Instance

Inst num

Release

RAC

Host

GELCPRO

4091276223

GELCPRO

1

10.2.0.1.0

NO

D0-LNXDB01

 

 

Snap Id

Snap Time

Sessions

Cursors/Session

Begin Snap:

26795

18-Jun-09 15:00:32

46

11.3

End Snap:

26796

18-Jun-09 16:00:56

45

6.8

Elapsed:

 

60.40 (mins)

 

 

DB Time:

 

63.25 (mins)

 

 

 

Top 5 Timed Events

Event

Waits

Time(s)

Avg Wait(ms)

% Total Call Time

Wait Class

CPU time

 

3,733

 

98.4

 

ARCH wait on SENDREQ

502

934

1,861

24.6

Network

log file parallel write

8,365

107

13

2.8

System I/O

log file sync

4,470

62

14

1.6

Commit

control file parallel write

2,717

17

6

.4

System I/O

 

可以看到数据库的负载是比较重的,而且问题出现时CPU大量消耗,感觉有CPU密集型的语句正在运行

然后查看TOP CPU SQL,和TOP time sql

 

SQL ordered by Elapsed Time

  • Resources reported for PL/SQL code includes the resources used by all SQL statements called by the code.
  • % Total DB Time is the Elapsed Time of the SQL statement divided into the Total Database Time multiplied by 100

Elapsed Time (s)

CPU Time (s)

Executions

Elap per Exec (s)

% Total DB Time

SQL Id

SQL Module

SQL Text

1,788

1,785

121

14.78

47.11

0sf192fw73ds9

 

DECLARE job BINARY_INTEGER := ...

1,780

1,779

1

1779.55

46.89

7s2s60d6c6tk7

 

begin pkg_ls_chl_com.p_backgro...

1,279

1,279

1

1279.34

33.71

cw1bax526a9am

 

DELETE T_COMMISION_INFO CI WHE...

1,137

1,125

114,068

0.01

29.95

3t3c1ju68qvkc

 

select /*+ all_rows */ count(...

 

 

SQL ordered by CPU Time

  • Resources reported for PL/SQL code includes the resources used by all SQL statements called by the code.
  • % Total DB Time is the Elapsed Time of the SQL statement divided into the Total Database Time multiplied by 100

CPU Time (s)

Elapsed Time (s)

Executions

CPU per Exec (s)

% Total DB Time

SQL Id

SQL Module

SQL Text

1,785

1,788

121

14.75

47.11

0sf192fw73ds9

 

DECLARE job BINARY_INTEGER := ...

1,779

1,780

1

1778.72

46.89

7s2s60d6c6tk7

 

begin pkg_ls_chl_com.p_backgro...

1,279

1,279

1

1279.08

33.71

cw1bax526a9am

 

DELETE T_COMMISION_INFO CI WHE...

1,125

1,137

114,068

0.01

29.95

3t3c1ju68qvkc

 

select /*+ all_rows */ count(...

 

根据报告可以确定问题语句的大概范围。

 

 

1DECLARE job BINARY_INTEGER := :job; next_date DATE := :mydate; broken BOOLEAN := FALSE; BEGIN pkg_life_public_back_process.p_run(2, 2); :mydate := next_date; IF broken THEN :b := 1; ELSE :b := 0; END IF; END;

2begin pkg_ls_chl_com.p_background_cal_commision(:1, :2, :3); end;

3DELETE T_COMMISION_INFO CI WHERE CI.AGGREGATION_ID = :B1

4select /*+ all_rows */ count(1) from "GELC_PROD"."T_COMMISSION_FEE" where "COMMISION_ID" = :1

 

 

其实前面两个语句也许不是问题的重点,然后通过日志挖掘挖掘日志4点到5点的时候日志切换最频繁的时候时间大概在5分钟以内切换的3个日志,发现出现了大量的DML语句,主要集中在两个表上

 

select seg_name,count(seg_name) count from v$logmnr_contents group by seg_name order by  count;

SEG_NAME                         COUNT

---------------------------------------

T_STAND_PREM_DETAIL              2028

T_SESSION_TRACE                  2096

SEQ$                             11245

T_PERFORMANCE_INFO               109267

T_COMMISION_INFO                 157757

AUD$                             249216

这里给出了最后6行,而AUD$是审计表,T_PERFORMANCE_INFOAWRRPT中并没有设计到,可以确定T_PERFORMANCE_INFO虽然DML次数多但是没有引起性能问题,剩下的就是T_COMMISION_INFO了,进一步查看:

SQL> select substrb(sql_redo,1,50) su,count(substrb(sql_redo,1,50)) te from v$logmnr_contents where SEG_NAME='T_COMMISION_INFO'

  2  group by substrb(sql_redo,1,50) order by te ;

 

SU                                                         TE

-------------------------------------------------- ----------

update "GELC_PROD"."T_COMMISION_INFO" set "COMM_ST       4609

delete from "GELC_PROD"."T_COMMISION_INFO" where "         14503

update "GELC_PROD"."T_COMMISION_INFO" set "MONEY"       23081

Unsupported                                                 25651

insert into "GELC_PROD"."T_COMMISION_INFO"("COMMIS      89913

 

这里出现了AWRRPT中指出的语句delete from "GELC_PROD"."T_COMMISION_INFO" where ",所以我确定真正的性能问题出在这里,因为日志挖掘和AWRRPT同时出现这样的语句。

 

进一步分析发现T_COMMISION_INFO表的数据量是比较大了10W以上,当然这里我觉得也不是问题所在,单一的一张表进行DELETE也不会出现如此的等待,然后我想可能是此表中的主键关联了大量的子表,在进行删除的时候,每一条记录中的主键都会去匹配子表,如果主表中的记录在子表中有引用,就会报错,如果没有引用才能被删除,这样如果子表的外键中不存在相应的索引就会进行全表扫描,引起大量的等待,而且会锁住子表,最初看到的多个表被锁住,也许就是这样引起的,当然如果一切成立最初看到的大事物的全表扫描,也是因为子表的全表扫描引起的。

通过语句

select CONSTRAINT_NAME,TABLE_NAME from dba_constraints where CONSTRAINT_TYPE='R' AND R_CONSTRAINT_NAME='PK_T_COMMISION_INFO';

发现了确实有6张表都引用了此表中的主键,这样没删除一条数据就会去全表扫描这6张表,

T_COMMISSION_FEE   

T_COUNT_DEPT_AWARD

T_PRODUCT_COMMISION

T_COMMISION_DETAIL

T_ADJUST_AWARD

T_REMAIN_COMM   

其中T_COMMISSION_FEE 10w多条数据

T_PRODUCT_COMMISION 3W多条数据

 

为了证明问题确实出在这里,在开发环境中我也做了试验,在T_COMMISSION_FEE插入了4W多条数据,然后开启SQL_TRACE后,用TKPROF进行格式化查看,

我使用的语句是

delete gelcdev216.T_COMMISION_INFO where COMMISION_ID>50000;

虽然这条语句报错了但是丝毫没有引向结果。

T_COMMISSION_FEE COMMISION_ID没有加索引的情况下,这条语句重启动到失败共耗时8秒,

并且TKPROF报告看到了这样的情况

select /*+ all_rows */ count(1)

from

 "GELCDEV216"."T_COMMISSION_FEE" where "COMMISION_ID" = :1

 

 

call     count       cpu    elapsed       disk      query    current        rows

------- ------  -------- ---------- ---------- ---------- ----------  ----------

Parse        1      0.00       0.00          0          0          0           0

Execute   1274      0.02       0.03          0          0          0           0

Fetch     1274      7.91       7.75          0     718536          0        1274

------- ------  -------- ---------- ---------- ---------- ----------  ----------

total     2549      7.94       7.79          0     718536          0        1274

 

这个消耗是比较严重的,而且我只是做的其中很小的一部分,而且

select /*+ all_rows */ count(1)  from "GELCDEV216"."T_COMMISSION_FEE" where "COMMISION_ID" = :1

正是在AWRRPT中出现的

select /*+ all_rows */ count(1) from "GELC_PROD"."T_COMMISSION_FEE" where "COMMISION_ID" = :1

就是因为大量的进行一致性验证而导致的语句,当然起初看到的全表扫描也是对子表的全表扫描,况且大量的锁出现部分也是由于这里的问题。

当我在T_COMMISSION_FEE COMMISION_ID建立索引过后运行同样的语句

delete gelcdev216.T_COMMISION_INFO where COMMISION_ID>50000;

 

时间只是0.5秒,而且在TKPROF中也不会出现相应扫描子表的语句,因为现在会去扫描新建的索引。

 

所以我觉得解决这个问题的方法就是在相应的数据较大的子表中建立索引,避免出现全表扫描,也不会去锁表,因为现在扫描的仅仅是索引中的块而已。方法及如下:

CREATE  INDEX  ****  ON T_COMMISSION_FEE(COMMISION_ID);

CREATE  INDEX  ****  ON T_PRODUCT_COMMISION(COMMISION_ID);

 

也许一条DELETE不会引起性能问题,但是如果进行批量的DELETE那小小的问题将会被放大很多。。。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
数据采集 Python
Python---Requests库的爬取性能分析
“任意”找个url,测试一下成功爬取100次网页的时间。(某些网站对于连续爬取页面将采取屏蔽IP的策略,所以,要避开这类网站。) import requests import time def getHtmlText(url): try: # try except:用于异常处理 r = requests.
1296 0
|
7月前
|
算法 Unix Linux
【C/C++ 实用工具】性能分析工具一览
【C/C++ 实用工具】性能分析工具一览
321 0
|
7月前
|
数据可视化 关系型数据库 编译器
【C/C++ 单线程性能分析工具 Gprof】 GNU的C/C++ 性能分析工具 Gprof 使用全面指南
【C/C++ 单线程性能分析工具 Gprof】 GNU的C/C++ 性能分析工具 Gprof 使用全面指南
1046 2
|
7月前
|
Web App开发 JavaScript 前端开发
JavaScript中的性能优化:代码优化技巧与性能分析工具
【4月更文挑战第22天】本文探讨JavaScript性能优化,包括代码优化技巧和性能分析工具。建议避免全局查找、减少DOM操作、使用事件委托、优化循环和异步编程以提升代码效率。推荐使用Chrome DevTools、Lighthouse和jsPerf等工具进行性能检测和优化。持续学习和实践是提升JavaScript应用性能的关键。
|
1月前
|
缓存 监控 Linux
Linux性能分析利器:全面掌握perf工具
【10月更文挑战第18天】 在Linux系统中,性能分析是确保软件运行效率的关键步骤。`perf`工具,作为Linux内核自带的性能分析工具,为开发者提供了强大的性能监控和分析能力。本文将全面介绍`perf`工具的使用,帮助你成为性能优化的高手。
126 1
|
1月前
|
缓存 监控 Linux
掌握Linux性能分析:深入探索perf工具
【10月更文挑战第26天】
45 1
|
2月前
|
Web App开发 监控 JavaScript
一些常用的 Vue 性能分析工具
【10月更文挑战第2天】
118 1
|
3月前
|
SQL 缓存 关系型数据库
MySQL高级篇——性能分析工具
MySQL的慢查询日志,用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long-query_time值的SQL,则会被记录到慢查询日志中。long_query_time的默认值为 10,意思是运行10秒以上(不含10秒)的语句,认为是超出了我们的最大忍耐时间值。它的主要作用是,帮助我们发现那些执行时间特别长的 SOL 查询,并且有针对性地进行优化,从而提高系统的整体效率。当我们的数据库服务器发生阻塞、运行变慢的时候,检查一下慢查询日志,找到那些慢查询,对解决问题很有帮助。
MySQL高级篇——性能分析工具
|
7月前
|
监控 Java 开发者
Java一分钟之-Java性能分析与调优:JProfiler, VisualVM等工具
【5月更文挑战第21天】本文介绍了Java性能优化的两个利器——JProfiler和VisualVM。JProfiler通过CPU Profiler、内存分析器和线程视图帮助解决过度CPU使用、内存泄漏和线程阻塞问题;VisualVM则聚焦于GC行为调整和类加载优化,以减少内存压力和提高应用性能。使用这些工具进行定期性能检查,是提升Java应用效率的关键。
204 0
|
3月前
|
监控 IDE Java
【Java性能调优新工具】JDK 22性能分析器:深度剖析,优化无死角!
【9月更文挑战第9天】JDK 22中的性能分析器为Java应用的性能调优提供了强大的支持。通过深度集成、全面监控、精细化分析和灵活报告生成等核心优势,性能分析器帮助开发者实现了对应用性能的全面掌控和深度优化。在未来的Java开发过程中,我们期待性能分析器能够继续发挥重要作用,为Java应用的性能提升贡献更多力量。