知识大全 诊断Oracle数据库Hanging问题

Posted 数据库

篇首语:如果惧怕前面跌宕的山岩,生命就永远只能是死水一潭。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 诊断Oracle数据库Hanging问题相关的知识,希望对你有一定的参考价值。

诊断Oracle数据库Hanging问题  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  适用范围 Oracle任何平台上的企业版数据库

  适用对象 所有数据库管理员和数据库支持人员

  本文目的 这篇文章主要描述用于诊断数据库hanging和性能问题的方法和 工具 这些问题可能是由于调整问题 设计问题或者Oracle的bug引起的

  将讨论如下的诊断步骤

   ) 描述清楚出现的现象问题

   ) 寻找具体错误

   ) 收集操作系统级别上的数据

   ) 获取systemstate和hanganalyze的dump

   ) 获取STATPACK的输出报告

   ) 获取PROCESSSTATE的dump

  注 可能很多时候没有必要关闭数据库来停止hanging 建议如果要关闭数据库之前获取这些诊断信息以便找出错误的原因所在

  下面就来具体讨论如何诊断数据库Hanging问题

  描述清楚出现的现象问题

  先弄清楚运行的数据库版本 需要完整的版本号 例如

  确定当前数据库是否是真的hanging还是处于活动状态但是运行的非常慢?检查下在Alert文件中是否还有日志切换 检查当前的CPU I/O 内存的利用率

  查看数据库hanging的开始时间 持续了多长时间?数据库hanging是否是突然发生还是由于增加的活动事务导致性能的逐步降低?当前有多少的连接用户?最近的系统负载是否是在上升?

  是否在初始化参数文件中设置了任何event?数据库当前正在做什么类型的事务?数据库的数据量多大?

  数据库是运行在集群环境吗?如果是集群数据库 那么关闭其他实例就留下一个实例 问题是否还持续存在?这里讨论的某些解决方法适用于集群数据库 但是大部分的方法不适合 例如 一个不大的buffer cache通常对于集群数据库来说意味着较好的性能 关于集群数据库的大部分hanging的问题这里不做讨论 其中包括PCM锁问题 pinging 空间管理问题 节点间并行查询调优 共享磁盘或者虚拟共享磁盘问题 网络问题 DLM问题等

  数据库是运行在MTS环境下吗?如果取消MTS 是否问题持续存在?是否使用了Oracle的应用或者工具?最近是否升级了数据库 应用 工具或者操作系统 硬件?问题发生的频率?是否能够重现问题?

  是否整个数据库都被hanging?

  所有的实例?所有的连接?所有的操作?所有的节点?

  首先确认是否能够执行查询select * from dual?日志文件多久切换一次?如果在Alert日志中有归档相关的错误信息 那么可以着手解决归档错误问题 因为归档问题经常会挂起数据库 例如 归档目的地空间满了 或者数据库处于归档模式下但是ARCH进程被停止了 一般可以先以sysdba权限连接到数据库中 执行ARCHIVE LOG LIST 查看数据库是否归档模式 是否启用了自动归档 一般如果没有启用自动归档 就很容易挂起数据库了 这个时候通常的做法就是把数据库改成自动归档模式或者是非归档模式

  一个指定的SQL语句操作?

   ) 如果是由于指定的SQL语句导致数据库挂起 先执行带有timed_statistics参数的TKPROF输出报告以及SQL语句的执行计划 然后就需要分SQL语句类型来分析了

   ) 如果是select语句 那么这个SQL语句应该是需要被调整 如果是一个非常复杂的SQL语句 那么尝试是否可以中断

   ) 如果是一个并行查询语句 可以参考监控当前并行查询运行状况脚本获得并行查询的执行计划 可能是空间事务竞争 如果在Alert日志文件中出现ORA 错误 那么请将临时表空间的参数pct_increase设置为 以便禁止SMON进程接合连续的extents 因此减少查询slaves的竞争 同时将数据文件尽量分散到不同的磁盘上去 减少磁盘I/O的竞争 适当增加sort_area_size的大小可能会 减少 并行度

   ) 如果是DML语句 那么可能是由于锁导致的 需要去获取v$lock的输出信息 关于锁的信息可以参考返回锁信息脚本 查看DML语句的对象上是否有限制或者触发器 有可能产生级联锁问题 把索引建立在相关的外键列上 这样会改变在父表上的锁行为

   ) 如果是DDL语句 可能是一个数据字典的相关问题 如果是create index语句则可能是一个空间事务竞争问题 调整I/O是一个比较好的方法 分布式I/O 分开索引和数据的存放空间 并行执行都是比较有用的方法 还可以设置初始化参数pre_page_sga为true

  指定的数据库对象?

  在指定对象能是否能做任何操作?做一个select count(*)是否有问题?如果只是update该对象存在问题 那么可能锁了 可以从上面 ) )中的脚本获取锁的信息

  是否预先分配好了空间给这个对象?如果是 那么将提高HWM并且导致全表扫描 以至于让数据库看起来像是 挂起 了 全表扫描总是会扫描HWM 即使表只存在很少的数据 解决方案就是尽量避免预分配extents除非马上要执行一个大的并行插入或者常规的装载 千万不要在直接装载的时候预分配extents

  如果对象是一个表 那么可以尝试

  ANALYZE TABLE <tablename> VALIDATE STRUCTURE CASCADE

  是否有报错 如果有报错 意味着表或者表上的索引存在坏块了 如果没有报错 那么继续尝试下面的SQL语句得到相应的的信息

  块级上的空间信息 一个高的chain out 也可能是问题的一部分

  SELECT *

  FROM sys dba dba_tables

  WHERE table_name = <TABLENAME>

  如果你有很多的更新和删除操作 那么一个不适合的索引也会造成问题 下面的SQL语句能帮你得到相关的索引信息

  SELECT i *

  FROM sys index_stats i sys dba_indexes d

  WHERE i name = d index_name

  AND d table_name = <TABLENAME> SELECT i *

  FROM sys index_stats i sys dba_indexes d

  WHERE i name = d index_name

  AND d table_name = <TABLENAME>

  如果是一个视图 那么需要查看视图建立在的表的信息

  SELECT text

  FROM sys dba_views

  WHERE view_name = <VIEWNAME>

  大规模的更新操作(例如使用SQLLDR IMPORT或者批处理操作)?

  这些操作上的表上存在有哪些索引?是否这些更新操作是在数据库高峰时期运行的?是否在Alert文件中存在有 checkpoint not plete 的错误信息?如果有表明重做日志文件太小了 需要调整它们 是否表空间被置于在热备模式下?(v$backup)如果表空间处于热备模式 那么产生日志 records 而不是 vectors 在一个大的更新操作中 就可能导致相当多的竞争和性能下降

  如果是一个SQLLDR操作 是否使用了传统路径方式?是否使用了REPLACE选项?(推荐使用TRUNCATE选项)在SQLLDR的控制文件中是否有sql functions?是否采用了readbuffers bindsize rows parallele方式?

  如果是一个IMPORT操作 是否使用了mit=y indexes=y constraints=y这些参数?是否增大了buffer?

  如果在update期间 有很多的用户在操作 那么容易造成资源竞争 导致系统变慢 回滚段 redo latches i/o和数据缓冲区都可能成为竞争的区域 我们可以从V$session_wait以及statpack中获取更多关于具体竞争的相关信息

  指定的包 存储过程或者PRO*C应用?

  首先需要查看这些包 存储过程或者PRO*C的具体内容 其中的哪个语句一直在执行?去掉这个语句后相应的程序是否能运行正常?如果是存储过程 那么可以利用DBMS_ALERT查看那里开始挂起了 如果是PRO*C程序 那么可以使用tkprof来识别 parsing 是否是瓶颈?如果是 那么可以使用预编译参数

  hold_cursor和release_cursor来调整 如果是一个包 那么尝试是否能单独执行每个存储过程?查看是否包和存储过程被刷新出了共享池 如果是 可以尝试把这些包和存储过程pin在共享池中

  SELECT *

  FROM v$db_object_cache

  WHERE name = <NAME>

  仅仅是远程访问?

  是否可以执行select * from dual@db_link?是否能够连接到远程的机器上执行本地的操作?是否是在做一个分布式的更新操作?初始化参数distributed_lock_timeout设置了多少?是否正在刷新快照?是否使用了对称复制?尝试做一个tkprof输出得到相应的执行计划 执行计划中如果标明是REMOTE的 那么就是远程执行的操作 如果在一个远程的机器上join两张表 那么请尝试在本地节点上生成join视图之后 查询这个视图 在sql操作中设置ARRAYSIZE 多使用pl/sql而不是单独的sql语句 使用显性游标这些都可以减少网络的负载

  使用第三方应用软件的操作

  是否能在sqlplus中重现问题?如果不可以重现 那么就需要联系第三方应用软件供应商寻求帮助

  数据关闭/启动过程中出现挂起

  关闭使用的什么参数?数据库是否crash了?如果是数据库启动挂起并且非正常关闭 但是在Alert日志文件中没有任何的错误 那么可能只是一个正常的实例恢复 如果在Alert文件中出现内部错误 系统错误 那么请尝试正常的关闭数据库然后启动

  下面是一个正常实例恢复的时候在Alert日志文件中列出的相关信息

  Starting ORACLE instance (normal)

  …………………

  Starting up ORACLE RDBMS Version

  System parameters with non default values

  ……………………

  Beginning crash recovery of threads

  Started redo scan

  Completed redo scan

   redo blocks read data blocks need recovery

  Recovery of Online Redo Log Thread Group Seq Reading mem

  Completed redo application

  Completed crash recovery at

  Thread logseq block scn

   data blocks read data blocks written redo blocks read

  SMON enabling cache recovery

  SMON enabling tx recovery

  Completed ALTER DATABASE OPEN

  如果正常的关闭或者immediate关闭挂起 那么意味着Oracle正在等待激活的会话退出

  在Unix系统上 还可以寻找正在挂起的启动或者关闭操作 然后trace pid

  寻找错误

   ) 检查AlertSID log告警日志文件看看是否存在错误信息 此告警日志文件的具体路径位置可以由初始化参数中的background_dump_dest中获得或者在sqlplus中执行show parameter dest获得

   ) 检查上述目录中的在数据库挂起时间生成的跟踪文件 查看里面的错误信息 不用搜索整个跟踪文件 相关的错误信息一般都是在文件的最开始出现

   ) 如果是远程访问的问题 那么还需要检查sql*net跟踪目录下的跟踪文件

   ) 检查系统信息的错误日志 在大多数的Unix下都是在/var/adm目录下

  输出查看相关的V$视图

  当数据库挂起的时候 执行下面的查询

  SPOOL v_views log

  SELECT *

  FROM v$parameter

  SELECT class value name

  FROM v$sysstat

  SELECT sid id id type lmode request

  FROM v$lock

  SELECT l latch# n name h pid l gets l misses

  l immediate_gets l immediate_misses l sleeps

  FROM v$latchname n v$latchholder h v$latch l

  WHERE l latch# = n latch#

  AND l addr = h laddr(+)

  SELECT *

  FROM v$session_wait

  ORDER BY sid

  /* 重复最后一个查询最少三遍 以确定哪个在重复等待*/

  SPOOL OFF

  如果是指定的查询被挂起了 可以使用下面的查询找出相应的查询SQL语句

  通过操作系统上的PID找出相应的SQL语句的SID

  SELECT s sid p spid

  FROM v$session s v$process p

  WHERE s paddr = p addr

  AND …… < p spid = <os pid> or perhaps

  s sid = <sid from v$session> >

  然后通过SID找出相应的SQL语句的具体内容

  SELECT s sid s status q sql_text

  FROM v$session s v$sqltext q

  WHERE s sql_hash_value = q hash_value

  AND s sql_address = q address

  AND s sid = <sid>

  order by q piece

  查询V$SESSION_WAIT视图看看当前的等待事件

  column sid format

  column seq# format

  column wait_time heading WTime format

  column event format a

  column p format

  column p format

  column p format

  select sid event seq# p p p wait_time from V$session_wait

  where sid=<SID>

  order by sid

  查询当前挂起数据库的SQL语句中的lockwait设置的是多少 如果非空 那么看看什么锁住了当前对象 是什么类型的锁

  SELECT lockwait

  FROM v$session

  WHERE sid = <sid>

  col Username format A

  col Sid format heading SID

  col Type format A

  col Lmode format heading HELD

  col Request format heading REQ

  col Id format

  col Id format

  select SN Username M Sid M Type

  DECODE(M Lmode None Null Row Share Row

  Excl Share S/Row Excl Exclusive

  LTRIM(TO_CHAR(Lmode ))) Lmode

  DECODE(M Request None Null Row Share Row

  Excl Share S/Row Excl Exclusive

  LTRIM(TO_CHAR(M Request ))) Request

  M Id M Id from V$SESSION SN V$LOCK M

  WHERE (SN Sid = M Sid and M Request ! = )

  or (SN Sid = M Sid and M Request = and Lmode != and (id id )

  in (select S Id S Id from V$LOCK S where Request != and S Id

  = M Id and S Id = M Id ) ) order by Id Id M Request

  查询v$process视图中的LATCHWAIT设置是多少?如果这个值非空 那么继续查是谁保存了这个latch

  SELECT latchwait

  FROM v$process

  WHERE spid = <pid> SELECT latchwait

  FROM v$process

  WHERE spid = <pid>

  column name format a heading LATCH NAME

  column pid heading HOLDER PID

  select c name a addr a gets a misses a sleeps

  a immediate_gets a immediate_misses b pid

  from v$latch a v$latchholder b v$latchname c

  where a addr = b laddr(+) and a latch# = c latch#

  and c name like &latch_name% order by a latch#

  上述这些保存了锁和latch的会话是否关闭了终端但是没有退出 这可能会导致一个影子进程继续保存那些资源 这样就需要杀掉相应的进程 可以使用如下语句

  alter system kill session <sid serial# from v$session>

  如果会话没有被挂起而只是运行缓慢 那么需要查看会话的具体信息

  SELECT s sid s value t name

  FROM v$sesstat s v$statname t

  WHERE s statistic# = t statistic#

  AND s sid = <sid>

  如果会话极度的缓慢或者是被挂起了 那么需要查看会话的等待信息

  SELECT *

  FROM v$session_wait

  where sid = <sid>

  如果是个分布式事务 那么需要在各个节点上都运行如下SQL语句

  SELECT * FROM dba_ pc_pending

  SELECT * FROM pending_sessions$

  SELECT * FROM pending_sub_sessions$

  SELECT * FROM dba_ pc_neighbors

  如果是MTS服务器 那么可以查看一下当前的dispatcher的繁忙程度

  select name neork status

  (busy /(busy + idle)) * % of time busy

  from v$dispatchers

  还可以查看V$SHARED_SERVERS视图获取相应的信息

  select name status requests (busy /(busy + idle)) * % of time busy

  from v$shared_servers

  收集操作系统的相关信息

   ) 简短的描述你的架构 包括CPU的数量 磁盘的数量 是否使用了裸设备 使用了NFS文件系统 共享磁盘……是否镜像了这些?

   ) 测量不同操作系统级别的活动 过量的CPU或者I/O 页面 交换区等 有许多的工具可以监测这些 例如TOP

  Unix上的工具 SAR VMSTAT NETSTAT TOP TRUSS等

  Vms上的工具 MONITOR ANALYZE PROCESS等

  Windows上的工具 Performance Monitor Event Monitor Dr Watson qslice等

   ) 检查系统的日志文件 在大多数Unix平台上日志文件都存在于/var/adm目录下

  获取SYSTEMSTATE和HANGANALYZE的dump

  这两个命令将在user_dump_dest目录下创建一个非常大的跟踪文件 初始化参数文件中的MAX_DUMP_FILE_SIZE参数确定了能够容纳的最大跟踪文件的大小 使用Oradebug命令设置unlimit将能允许执行一个完全的dump 请确认整个数据库已经挂起或者即将挂起 并且在Alert告警日志文件中没有任何归档的错误的时候才可以做此操作

  注意 当数据库是集群数据库的时候 如果需要诊断挂起的问题 则需要在每个节点上都执行systemstate dump操作 建议做 次左右 以便能够确定数据库或者进程是否是真的挂起还是激活状态

  对于Oracle x to x的版本

  $ svrmgrl

  svrmgr> connect internal

  svrmgr>ALTER SESSION SET EVENTS IMMEDIATE TRACE NAME HANGANALYZE LEVEL

  wait seconds

  svrmgr>ALTER SESSION SET EVENTS IMMEDIATE TRACE NAME HANGANALYZE LEVEL

  EXIT …… then reconnect

  svrmgr>ALTER SESSION SET MAX_DUMP_FILE_SIZE=UNLIMITED

  svrmgr>ALTER SESSION SET EVENTS IMMEDIATE TRACE NAME SYSTEMSTATE LEVEL

  wait seconds

  svrmgr>ALTER SESSION SET EVENTS IMMEDIATE TRACE NAME SYSTEMSTATE LEVEL

  wait seconds

  svrmgr>ALTER SESSION SET EVENTS IMMEDIATE TRACE NAME SYSTEMSTATE LEVEL

  对于Oracle 或者更高的版本

  $ sqlplus /nolog

  connect / as sysdba

  oradebug setmypid

  oradebug unlimit

  oradebug hanganalyze

  wait seconds

  oradebug hanganalyze

  oradebug dump systemstate

  wait seconds

  oradebug dump systemstate

  wait seconds

  oradebug dump systemstate

  获取STATPACK的输出报告

  对于如何得到和分析statpack的输出报告 可以参考eygle的个人网站上的文章

  

  获取PROCESSSTATE的dump

  获取processstate dump 可以使用如下命令 建议执行三遍 将可以在user_dump_dest目录下找到生成的跟踪文件

  $ sqlplus /as sysdba

  oradebug setospid <process ID>

  oradebug unlimit

  如果要获取errorstacks dump 可以使用如下命令 建议执行三遍 同样可以在user_dump_dest目录下找到生成的跟踪文件

  $ sqlplus /as sysdba

  oradebug setospid <process ID>

  oradebug unlimit

cha138/Article/program/Oracle/201311/18122

相关参考

知识大全 ORACLE数据库常见问题诊断方法

ORACLE数据库常见问题诊断方法  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  ORACLE的

知识大全 ORACLE数据库问题诊断方法 :常见错误篇

ORACLE数据库问题诊断方法:常见错误篇  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  ORA

知识大全 Oracle数据库常见问题诊断-SQL*NET篇

Oracle数据库常见问题诊断-SQL*NET篇  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  

知识大全 用Oracle中的Statspack诊断数据库性能实例

用Oracle中的Statspack诊断数据库性能实例  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧

知识大全 Oracle索引问题诊断与优化

Oracle索引问题诊断与优化  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  一实验  crea

知识大全 Oracle数据库中汉字长度的问题

Oracle数据库中汉字长度的问题  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  问题  var

知识大全 Oracle数据库exp导出问题

Oracle数据库|exp导出问题  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  昨天payme

知识大全 Oracle数据库常见问题答疑二

Oracle数据库常见问题答疑二  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  问利用QUERY

知识大全 Oracle数据库频繁归档问题的解决办法

Oracle数据库频繁归档问题的解决办法  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Orac

知识大全 Oracle数据库中有关触发器问题

Oracle数据库中有关触发器问题  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  触发器是一种特