百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

【Oracle】数据库执行慢问题排查(oracle数据库响应慢)

sinye56 2024-10-09 19:49 7 浏览 0 评论

文中使用的Oracle版本为10g。

这是之前在工作中遇到的慢查询排查记录,为了防杠先做个声明。

“All Roads Lead to Rome”

以下方法是本人处理思路以及在排除掉其他外部因素后,只针对数据库层面的排查内容。当然了肯定有更好的排查方式,这里只是提供一个方案而已。

1. 若出现插入速度慢或者无法插入数据的情况下,先检查表空间

SELECT UPPER(F.TABLESPACE_NAME) "表空间名",
D.TOT_GROOTTE_MB "表空间大小(M)",
D.TOT_GROOTTE_MB - F.TOTAL_BYTES "已使用空间(M)",
TO_CHAR(ROUND((D.TOT_GROOTTE_MB - F.TOTAL_BYTES) / D.TOT_GROOTTE_MB * 100, 2), '990.99') || '%' "使用比",
F.TOTAL_BYTES "空闲空间(M)",
F.MAX_BYTES "最大块(M)"
FROM (SELECT TABLESPACE_NAME,
        ROUND(SUM(BYTES) / (1024 * 1024), 2) TOTAL_BYTES,
        ROUND(MAX(BYTES) / (1024 * 1024), 2) MAX_BYTES   
        FROM SYS.DBA_FREE_SPACE   
        GROUP BY TABLESPACE_NAME) F,
(SELECT DD.TABLESPACE_NAME,
           ROUND(SUM(DD.BYTES) / (1024 * 1024), 2) TOT_GROOTTE_MB   
           FROM SYS.DBA_DATA_FILES DD   
           GROUP BY DD.TABLESPACE_NAME) D
WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME
--and F.TABLESPACE_NAME = '<tablespace>'
ORDER BY 1;

上面的脚本已经将列名都用中文标识清楚了,若用户表空间使用率达到峰值,则基本只能查询,其他的操作都不能做了。除此之外,本脚本还可以看到系统的表空间情况,其中值得注意的是UNDOTBS1这个表空间,如下图:

这个是回滚表空间,越大越能够储存回滚段。在做提交操作或者复杂运算的时候这里的使用率会飞涨。这个表空间是系统自动回收的,当系统判断资源不需要被使用之后表空间将会被回收。但若这个表空间长时间不回收就需要留意是否存在大批量的提交操作甚至锁表情况出现。

2. 表空间正常但发现只能查询不能修改或者插入时,可以初步判定存在锁表的可能性

通过以下语句查询是否存在表级锁

SELECT SESS.SID,
       SESS.SERIAL#,
       LO.ORACLE_USERNAME,
       LO.OS_USER_NAME,
       AO.OBJECT_NAME,
       LO.LOCKED_MODE
  FROM V$LOCKED_OBJECT LO, DBA_OBJECTS AO, V$SESSION SESS
 WHERE AO.OBJECT_ID = LO.OBJECT_ID
   AND LO.SESSION_ID = SESS.SID;

一般情况下会在做DML操作时系统会自动分配一个行级排它锁。同时这个事务就会获得一个表锁以防止其他的DDL操作影响DML操作。以上说的都是系统自动操作的,但是需要用到上面语句来进行查询的时候应该大多数情况都是产生了死锁,即多个DML操作产生了冲突引起的锁。这个时候就只能查询出来锁的SID和SERIAL#来将其KILL掉。

除此之外还有其他找锁表的语句,譬如:

SELECT (SELECT USERNAME FROM V$SESSION WHERE SID = A.SID) BLOCKER,
       A.SID,
       'IS BLOCKING',
       (SELECT USERNAME FROM V$SESSION WHERE SID = B.SID) BLOCKEE,
       B.SID
  FROM V$LOCK A, V$LOCK B
 WHERE A.BLOCK = 1
   AND B.REQUEST > 0
   AND A.ID1 = B.ID1
   AND A.ID2 = B.ID2;

找到SID和SERIAL#字段信息并KILL掉当前死锁执行脚本如下:

ALTER SYSTEM KILL SESSION 'SID,SERIAL#';

还有很多情况也会产生出锁表的现象,不过本人经历过最多的锁表原因都在于:

1) 应用程序的编写不当引起,包括JDBC连接没有正常关闭,通过循环提交负责级联更新操作等

2) 数据库 存储过程/触发器 编写逻辑混乱引起的同表资源抢占(一个操作没有完成就又要提交另一个操作)

3) 数据库利用定时器模仿多线程进行同表数据DML操作

3. 服务器端出现多个Oracle进程并CPU占用率高

要想知道是那个数据库用户在占用CPU可以使用以下语句找到:

SELECT A.SID,
       SPID,
       STATUS,
       SUBSTR(A.PROGRAM, 1, 40) PROG,
       A.TERMINAL,
       OSUSER,
       VALUE / 60 / 100 VALUE
  FROM V$SESSION A, V$PROCESS B, V$SESSTAT C
 WHERE C.STATISTIC# = 12
   AND C.SID = A.SID
   AND A.PADDR = B.ADDR 
   -- AND STATUS = 'ACTIVE'  
 ORDER BY VALUE DESC;

执行后如下图所示,可以通过图中的字段知道哪个用户是通过哪种方式连接到数据库的,是否在线状态,数据库中执行id是什么,操作系统中是那个用户,CPU耗时多长时间,以此来定为那个用户。

4. 进一步深挖究竟执行什么导致CPU使用率高

SELECT OSUSER, USERNAME, SQL_TEXT, ADDRESS, HASH_VALUE
FROM V$SESSION A, V$SQLTEXT B
WHERE A.SQL_ADDRESS = B.ADDRESS
--AND USERNAME = 'I_INFO' 
ORDER BY ADDRESS, PIECE;

执行之后如下图所示,查询出来后可以根据USERNAME来进行筛选,再来拿到语句的ADDRESS(SGA内存地址)和HASH_VALUE(Oracle Hash值)进行后续查询。

下面脚本将根据ADDRESS和HASH_VALUE来找到对应SQL执行性能消耗情况:

SELECT HASH_VALUE,
       BUFFER_GETS,
       DISK_READS,
       EXECUTIONS,
       PARSE_CALLS,
       CPU_TIME
  FROM V$SQLAREA
 WHERE HASH_VALUE = 1977390476
   AND ADDRESS = HEXTORAW('000000018B83E578');

执行之后可以看到BUFFER_GETS(所有子游标运行这条语句导致的读内存次数),DISK_READS(所有子游标运行这条语句导致的读磁盘次数),EXECUTIONS(所有子游标的执行这条语句次数),PARSE_CALLS (语句的解析调用(软、硬)次数),CPU_TIME (语句被解析和执行的CPU时间),如下图:

一般来说EXECUTIONS,BUFFER_GETS越高表示读内存多,磁盘少是比较理想的状态,因此越高越好。

之后若发现语句资源消耗异常可以从SQL_TEXT找到对应的语句,放到执行计划里面进行分析看看具体是那个地方造成性能问题。

5. 还有另一种解法获取等待时间长的用户和执行语句

SELECT S.SID, S.USERNAME, SUM(A.WAIT_TIME + A.TIME_WAITED) TOTAL_WAIT_TIME
  FROM V$ACTIVE_SESSION_HISTORY A, V$SESSION S
 WHERE A.SAMPLE_TIME BETWEEN SYSDATE - 30 / 2880 AND SYSDATE
 GROUP BY S.SID, S.USERNAME
 ORDER BY TOTAL_WAIT_TIME DESC;
SELECT A.PROGRAM,
       A.SESSION_ID,
       A.USER_ID,
       D.USERNAME,
       S.SQL_TEXT,
       SUM(A.WAIT_TIME + A.TIME_WAITED) TOTAL_WAIT_TIME
  FROM V$ACTIVE_SESSION_HISTORY A, V$SQLAREA S, DBA_USERS D
 WHERE A.SAMPLE_TIME BETWEEN SYSDATE - 30 / 2880 AND SYSDATE
   AND A.SQL_ID = S.SQL_ID
   AND A.USER_ID = D.USER_ID
 GROUP BY A.PROGRAM, A.SESSION_ID, A.USER_ID, S.SQL_TEXT, D.USERNAME;

两个脚本里面都有TOTAL_WAIT_TIME字段,这个字段就是这些用户和SQL从产生开始到目前为止等待的最长时间,可以根据这个定位用户和SQL。

若问题仍然存在,就需要注意内存使用情况和Oracle的SGA和PGA分配情况(这个网上有太多方法了就不再叙述)。


后日谈

在另一次慢查询分析时在执行到了第四步“进一步深挖究竟执行什么导致CPU使用率高”后找到了执行慢的语句,进一步执行分析计划后看到语句本应该是主键的ID字段没有走到索引,本以为Oracle会自动基于成本规则选择了别的执行方式。但并没有......后来将这个结果与所在项目组沟通才知道他们在做数据迁移时执行脚本用CTAS方式建表忘记额外生成主键了。

其实我想说的是,只要不是过于复杂的业务过程或者大规模运算的情况下哪有那么多性能问题,往往性能问题都是因为一些“粗心大意”下引起的,听我说多用checklist准没错的。

相关推荐

Linux基础知识之修改root用户密码

现象:Linux修改密码出现:Authenticationtokenmanipulationerror。故障解决办法:进入单用户,执行pwconv,再执行passwdroot。...

Linux如何修改远程访问端口

对于Linux服务器而言,其默认的远程访问端口为22。但是,出于安全方面的考虑,一般都会修改该端口。下面我来简答介绍一下如何修改Linux服务器默认的远程访问端口。对于默认端口而言,其相关的配置位于/...

如何批量更改文件的权限

如果你发觉一个目录结构下的大量文件权限(读、写、可执行)很乱时,可以执行以下两个命令批量修正:批量修改文件夹的权限chmod755-Rdir_name批量修改文件的权限finddir_nam...

CentOS「linux」学习笔记10:修改文件和目录权限

?linux基础操作:主要介绍了修改文件和目录的权限及chown和chgrp高级用法6.chmod修改权限1:字母方式[修改文件或目录的权限]u代表所属者,g代表所属组,o代表其他组的用户,a代表所有...

Linux下更改串口的权限

问题描述我在Ubuntu中使用ArduinoIDE,并且遇到串口问题。它过去一直有效,但由于可能不必要的原因,我觉得有必要将一些文件的所有权从root所有权更改为我的用户所有权。...

Linux chown命令:修改文件和目录的所有者和所属组

chown命令,可以认为是"changeowner"的缩写,主要用于修改文件(或目录)的所有者,除此之外,这个命令也可以修改文件(或目录)的所属组。当只需要修改所有者时,可使用...

chmod修改文件夹及子目录权限的方法

chmod修改文件夹及子目录权限的方法打开终端进入你需要修改的目录然后执行下面这条命令chmod777*-R全部子目录及文件权限改为777查看linux文件的权限:ls-l文件名称查看li...

Android 修改隐藏设置项权限

在Android系统中,修改某些隐藏设置项或权限通常涉及到系统级别的操作,尤其是针对非标准的、未在常规用户界面显示的高级选项。这些隐藏设置往往与隐私保护、安全相关的特殊功能有关,或者涉及开发者选项、权...

完蛋了!我不小心把Linux所有的文件权限修改了!在线等修复!

最近一个客户在群里说他一不小心把某台业务服务器的根目录权限给改了,本来想修改当前目录,结果执行成了根目录。...

linux改变安全性设置-改变所属关系

CentOS7.3学习笔记总结(五十八)-改变安全性设置-改变所属关系在以前的文章里,我介绍过linux文件权限,感兴趣的朋友可以关注我,阅读一下这篇文章。这里我们不在做过的介绍,注重介绍改变文件或者...

Python基础到实战一飞冲天(一)--linux基础(七)修改权限chmod

#07_Python基础到实战一飞冲天(一)--linux基础(七)--修改权限chmod-root-groupadd-groupdel-chgrp-username-passwd...

linux更改用户权限为root权限方法大全

背景在使用linux系统时,经常会遇到需要修改用户权限为root权限。通过修改用户所属群组groupid为root,此操作只能使普通用户实现享有部分root权限,普通用户仍不能像root用户一样享有超...

怎么用ip命令在linux中添加路由表项?

在Linux中添加路由表项,可以使用ip命令的route子命令。添加路由表项的基本语法如下:sudoiprouteadd<network>via<gateway>这...

Linux配置网络

1、网卡名配置相关文件回到顶部网卡名命名规则文件:/etc/udev/rules.d/70-persistent-net.rules#PCIdevice0x8086:0x100f(e1000)...

Linux系列---网络配置文件

1.网卡配置文件在/etc/sysconfig/network-scripts/下:[root@oldboynetwork-scripts]#ls/etc/sysconfig/network-s...

取消回复欢迎 发表评论: