网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > 数据库 > Oracle教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
数据库:数据库教程,数据库技巧,Oracle教程,MySQL教程,Sybase教程,Access教程,DB2教程,数据库安全,数据库文摘
本月文章推荐
.oracle数据库开发的一些经验积累.
.分析诊断进程跟踪文件工具ASS.AW.
.ORACLE SQL性能优化系列 (七).
.Oracle数据库文件移动.
.RedHat 日志文件.
.Oracle 9i 在AIX上的安装.
.Index of Oracle.
.自己动手写操作系统(二).
.Oracle 10g RAC与SLES9.
.浅谈权限管理的对象模型和实现.
.日常监测分析数据库的DBA_Monito.
.Oracle及IBM称SQL无新意 微软以商.
.PL/SQL中使用or展开进行sql调整.
.zSeries的Linux有什么主要元素构.
.如何移动表来达到减小数据文件大.
.关于Oracle Metalink的常见问题.
.ORACLE没有自动增长的数据类型.
.Oracle9i初始化参数中文说明(6).
.关于Oracle数据库中密码安全管理.
.清单:负载测试 SQL Server性能调.

诊断Oracle数据库Hanging问题

发表日期:2008-2-9


    适用范围:Oracle任何平台上的企业版数据库     适用对象:所有数据库治理员和数据库支持人员     本文目的:这篇文章主要描述用于诊断数据库hanging和性能问题的方法和 工具,这些问题可能是由于调整问题,设计问题或者Oracle的bug引起的。     将讨论如下的诊断步骤:     1) 描述清楚出现的现象问题     2) 寻找具体错误     3) 收集操作系统级别上的数据     4) 获取systemstate和hanganalyze的dump     5) 获取STATPACK的输出报告     6) 获取PROCESSSTATE的dump     注:可能很多时候没有必要关闭数据库来停止hanging,建议假如要关闭数据库之前获取这些诊断信息以便找出错误的原因所在。     下面就来具体讨论如何诊断数据库Hanging问题。     描述清楚出现的现象问题:     先弄清楚运行的数据库版本,需要完整的版本号,例如9.2.0.4.     确定当前数据库是否是真的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语句操作?     1) 假如是由于指定的SQL语句导致数据库挂起,先执行带有timed_statistics参数的TKPROF输出报告以及SQL语句的执行计划,然后就需要分SQL语句类型来分析了:     2) 假如是select语句,那么这个SQL语句应该是需要被调整,假如是一个非常复杂的SQL语句,那么尝试是否可以中断。     3) 假如是一个并行查询语句,可以参考监控当前并行查询运行状况脚本获得并行查询的执行计划。可能是空间事务竞争,假如在Alert日志文件中出现ORA-1575错误,那么请将临时表空间的参数pct_increase设置为0以便禁止SMON进程接合连续的extents,因此减少查询slaves的竞争。同时将数据文件尽量分散到不同的磁盘上去,减少磁盘I/O的竞争,适当增加sort_area_size的大小可能会‘减少’并行度。     4) 假如是DML语句,那么可能是由于锁导致的,需要去获取v$lock的输出信息,关于锁的信息可以参考返回锁信息脚本。查看DML语句的对象上是否有限制或者触发器,有可能产生级联锁问题。把索引建立在相关的外键列上,这样会改变在父表上的锁行为。     5) 假如是DDL语句,可能是一个数据字典的相关问题。假如是create index语句则可能是一个空间事务竞争问题。调整I/O是一个比较好的方法,分布式I/O,分开索引和数据的存放空间,并行执行都是比较有用的方法,还可以设置初始化参数pre_page_sga为true.    指定的数据库对象?
    在指定对象能是否能做任何操作?做一个select count(*)是否有问题?假如只是update该对象存在问题,那么可能锁了,可以从上面3)、4)中的脚本获取锁的信息。     是否预先分配好了空间给这个对象?假如是,那么将提高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 complete"的错误信息?假如有表明重做日志文件太小了,需要调整它们。是否表空间被置于在热备模式下?(v$backup)假如表空间处于热备模式,那么产生日志“records”而不是“vectors”,在一个大的更新操作中,就可能导致相当多的竞争和性能下降。     假如是一个SQLLDR操作,是否使用了传统路径方式?是否使用了REPLACE选项?(推荐使用TRUNCATE选项)在SQLLDR的控制文件中是否有sql functions?是否采用了readbuffers,bindsize,rows,parallele方式?     假如是一个IMPORT操作,是否使用了commit=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: 10.2.0.1.0.     System parameters with non-default values:     ……………………     Beginning crash recovery of 1 threads     Started redo scan     Completed redo scan     120 redo blocks read, 46 data blocks need recovery     Recovery of Online Redo Log: Thread 1 Group 2 Seq 143 Reading mem 0     Completed redo application     Completed crash recovery at     Thread 1: logseq 143, block 4358, scn 512699     46 data blocks read, 46 data blocks written, 120 redo blocks read     SMON: enabling cache recovery     SMON: enabling tx recovery     Completed: ALTER DATABASE OPEN     假如正常的关闭或者immediate关闭挂起,那么意味着Oracle正在等待激活的会话退出。     在Unix系统上,还可以寻找正在挂起的启动或者关闭操作,然后trace pid.     寻找错误:     1) 检查AlertSID.log告警日志文件看看是否存在错误信息,此告警日志文件的具体路径位置可以由初始化参数中的background_dump_dest中获得或者在sqlplus中执行show parameter dest获得。     2) 检查上述目录中的在数据库挂起时间生成的跟踪文件。查看里面的错误信息,不用搜索整个跟踪文件,相关的错误信息一般都是在文件的最开始出现。     3) 假如是远程访问的问题,那么还需要检查sql*net跟踪目录下的跟踪文件。     4) 检查系统信息的错误日志,在大多数的Unix下都是在/var/adm目录下。     输出查看相关的V$视图:     当数据库挂起的时候,执行下面的查询:     SPOOL v_views.log;     SELECT *     FROM v$parameter;     SELECT class, value, name     FROM v$sysstat;     SELECT sid, id1, id2, 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 990     column seq# format 99990     column wait_time heading 'WTime' format 99990     column event format a30     column p1 format 9999999990     column p2 format 9999999990     column p3 format 9990     select sid,event,seq#,p1,p2,p3,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 A15     col Sid format 9990 heading SID     col Type format A4     col Lmode format 990 heading 'HELD'     col Request format 990 heading 'REQ'     col Id1 format 9999990     col Id2 format 9999990     select SN.Username, M.Sid, M.Type,     DECODE(M.Lmode, 0, 'None', 1, 'Null', 2, 'Row Share', 3, 'Row     Excl.', 4, 'Share', 5, 'S/Row Excl.', 6, 'Exclusive',     LTRIM(TO_CHAR(Lmode,'990'))) Lmode,     DECODE(M.Request, 0, 'None', 1, 'Null', 2, 'Row Share', 3, 'Row     Excl.', 4, 'Share', 5, 'S/Row Excl.', 6, 'Exclusive',     LTRIM(TO_CHAR(M.Request, '990'))) Request,     M.Id1, M.Id2 from V$SESSION SN, V$LOCK M     WHERE (SN.Sid = M.Sid and M.Request ! = 0)
    or (SN.Sid = M.Sid and M.Request = 0 and Lmode != 4 and (id1, id2)     in (select S.Id1, S.Id2 from V$LOCK S where Request != 0 and S.Id1     = M.Id1 and S.Id2 = M.Id2) ) order by Id1, Id2, 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 a32 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_2pc_pending;     SELECT * FROM pending_sessions$;     SELECT * FROM pending_sub_sessions$;     SELECT * FROM dba_2pc_neighbors;     假如是MTS服务器,那么可以查看一下当前的dispatcher的繁忙程度:     select name,network,status,     (busy /(busy + idle)) * 100 "% of time busy"     from v$dispatchers;     还可以查看V$SHARED_SERVERS视图获取相应的信息:     select name,status,requests, (busy /(busy + idle)) * 100 "% of time busy"     from v$shared_servers     收集操作系统的相关信息:     1) 简短的描述你的架构,包括CPU的数量,磁盘的数量。是否使用了裸设备,使用了NFS文件系统,共享磁盘……是否镜像了这些?     2) 测量不同操作系统级别的活动:过量的CPU或者I/O,页面,交换区等。有许多的工具可以监测这些,例如TOP.     Unix上的工具:SAR,VMSTAT,NETSTAT,TOP,TRUSS等
    Vms上的工具:MONITOR,ANALYZE,PROCESS等     Windows上的工具:Performance Monitor, Event Monitor, Dr. Watson,qslice等     3) 检查系统的日志文件,在大多数Unix平台上日志文件都存在于/var/adm目录下。     获取SYSTEMSTATE和HANGANALYZE的dump     这两个命令将在user_dump_dest目录下创建一个非常大的跟踪文件,初始化参数文件中的MAX_DUMP_FILE_SIZE参数确定了能够容纳的最大跟踪文件的大小。使用Oradebug命令设置unlimit将能答应执行一个完全的dump.请确认整个数据库已经挂起或者即将挂起,并且在Alert告警日志文件中没有任何归档的错误的时候才可以做此操作。     注重:当数据库是集群数据库的时候,假如需要诊断挂起的问题,则需要在每个节点上都执行systemstate dump操作,建议做3次左右,以便能够确定数据库或者进程是否是真的挂起还是激活状态。     对于Oracle 8.0.5.x to 8.1.7.x的版本:     $ svrmgrl     svrmgr> connect internal     svrmgr>ALTER SESSION SET EVENTS 'IMMEDIATE TRACE NAME HANGANALYZE LEVEL 3';     wait 90 seconds     svrmgr>ALTER SESSION SET EVENTS 'IMMEDIATE TRACE NAME HANGANALYZE LEVEL 3';     EXIT …… then reconnect     svrmgr>ALTER SESSION SET MAX_DUMP_FILE_SIZE=UNLIMITED;     svrmgr>ALTER SESSION SET EVENTS 'IMMEDIATE TRACE NAME SYSTEMSTATE LEVEL 10';     wait 90 seconds     svrmgr>ALTER SESSION SET EVENTS 'IMMEDIATE TRACE NAME SYSTEMSTATE LEVEL 10';     wait 90 seconds     svrmgr>ALTER SESSION SET EVENTS 'IMMEDIATE TRACE NAME SYSTEMSTATE LEVEL 10';    对于Oracle 9.2.0.1或者更高的版本:     $ sqlplus /nolog     connect / as sysdba     oradebug setmypid     oradebug unlimit     oradebug hanganalyze 3     wait 90 seconds     oradebug hanganalyze 3     oradebug dump systemstate 10     wait 90 seconds     oradebug dump systemstate 10     wait 90 seconds     oradebug dump systemstate 10     获取STATPACK的输出报告     对于如何得到和分析statpack的输出报告,可以参考eygle的个人网站上的文章。     http://www.eygle.com/archives/2004/11/statspack_list.Html     获取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     oradebug dump errorstack 3
上一篇:如何恢复只有完好数据文件的oracle数据库? 人气:598
下一篇:Oracle 9i Real Application Clusters 人气:1076
浏览全部Oracle教程的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐