暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

oracle 常见问题诊断思路(一招鲜、吃遍天)

华创信科 2017-07-31
629



1、文章介绍

该文档介绍了数据库出现故障情况下,诊断故障的思路,需要收集的信息,处理问题的方法,以及诊断故障方面的测试案例。

 

2 、性能问题处理思路

在数据库发生故障情况下,根据具体故障采取必要的应急处理措施尽快恢复服务。

通常的故障应急处理流程如下:

故障现场信息采集*—故障性质确认—故障处理–服务恢复。

 

2.1 enq: SQ - contention

问题原因:是由于sequence的cache不足够大引起的。

解决方法:

找出被阻塞sql语句的sql_id,以及引起阻塞的对象ROW_WAIT_OBJ#(dba_objects.object_id).

su - Oracle

sqlplus as sysdba

SQL> select inst_id,

       sid,

       event,

       sql_hash_value,

       ROW_WAIT_OBJ#,

       sql_id,

       blocking_session,

       blocking_instance

  from gv$session where event = 'enq: SQ - contention';


根据sql_id查看被阻塞的sql

su - oracle

sqlplus as sysdba

SQL> select SQL_FULLTEXT fromv$sqlarea where sql_id = '&sql_id';

 

根据object_id查看引起阻塞的对象(sequence名称)

su - oracle

sqlplus as sysdba

SQL> Select owner,object_name,object_type from dba_objects where object_id=&oi;

 

最后适当调整sequence 的cache大小:

SQL> alter sequence  seq_name  cache xxxxxx;


2.2   enq: TX

问题原因:

enq: TX - row lock contention 通常是application级别的问题。

enq是一种保护共享资源的锁定机制,排队机制,先进先出(FIFO)。

解决方法:

找出被阻塞的sql_id,引起阻塞的对象ROW_WAIT_OBJ#(dba_objects.object_id).

su - oracle

sqlplus as sysdba

SQL> select inst_id,

       sid,

       event,

       sql_hash_value,

       ROW_WAIT_OBJ#,

       sql_id,

       blocking_session,

       blocking_instance

  fromgv$session where event =  like 'enq:TX%');


查看被阻塞的sql

su - oracle

sqlplus as sysdba

SQL> select SQL_FULLTEXT fromv$sqlarea where sql_id = '&sql_id';

 

查看引起阻塞的对象的名称

su - oracle

sqlplus as sysdba

SQL> Selectowner,object_name,object_type from dba_objects where object_id=&oi;

 

查看锁和被锁关系:

su - oracle

sqlplus as sysdba

SQL>SELECTdecode(request,0,'holder: ','waiter: ') || inst_id || ':' || sid sess,

id1, id2, lmode, request, type

FROM gv$lock

WHERE (id1, id2, type) in ( SELECT id1, id2,type FROM gv$lock WHERE request > 0 )

order by id1, request;

 

SESS                  ID1        ID2     LMODE    REQUEST TY

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

holder: 1:195      589856        209          6          0 TX

waiter: 1:194      589856        209          0          6 TX

waiter: 1:193      589856        209         0          6 TX

holder: 1:211      655391        206          6          0 TX

waiter: 1:213      655391        206          0          6 TX

waiter: 1:200      655391        206          0          6 TX


找出holder后面跟着waiter的session实例1的195和221号session,和应用维护人员协商是否杀掉这些阻塞其他连接的session。如果需要杀掉这些session执行下面的sql

select'alter system kill session '''||SID||','||SERIAL#||''';' from gv$session whereinst_id =1 and sid in (195,221);

'ALTERSYSTEMKILLSESSION'''||SID||','||SERIAL#||''';'

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

alter system kill session '195,12';

alter system kill session '221,1';

然后执行下面的sql杀掉session

SQL>Conn/ as sysdba

SQL>alter system kill session '195,12';

SQL>alter system kill session '221,1';


或者根据session的sid,找到对应的操作系统进程号,从操作系统杀掉这个进程

Conn as sysdba

SQL> select spid from v$process whereaddr in (select paddr from v$session where sid =221);

 

SPID

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

2769

 

SQL> select spid from v$process whereaddr in (select paddr from v$session where sid =195);

 

SPID

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

3102

SQL> exit

Session 195对应的操作系统进程是3102,查看这个进程是应用进程,并杀掉这个进程

 [oracle@Linux ~]$ ps -ef|grep 3102

oracle   3102  3101  0 11:04 ?        00:00:00 oracleora10g(DESCRIPTION=(LOCAL=NO)(ADDRESS=(PROTOCOL=beq)))

oracle   8053  2915  0 14:16 pts/0    00:00:00 grep 3102

[oracle@linux ~]$ kill 3102

杀掉进程会让启动这些进程的应用停掉。别杀数据库后台的进程(pmon,dbwn,lgwr,ckpt,smon,mmon,mmnl,arcn),否则会引起数据库异常,严重的会让数据库crash掉。

 

2.3   使用sql tuning Advisor

在sqlplus下依次执行下面脚本:


创建优化task:

su - oracle

sqlplus as sysdba

SQL> DECLARE

 my_task_name VARCHAR2(30);

 v_sql_id v$sqlarea.sql_id%type;

BEGIN

 my_task_name :=DBMS_SQLTUNE.CREATE_TUNING_TASK

(sql_id    => v_sql_id,

User_name   => 'USERNAME',

task_name   => 'my_sql_tuning_task');

END;

/


执行优化task:

execDBMS_SQLTUNE.EXECUTE_TUNING_TASK( task_name => 'my_sql_tuning_task' );

查看优化建议并查看建议是否适用

SET LONG 1000

SET LONGCHUNKSIZE 1000

SET LINESIZE 100

SELECTDBMS_SQLTUNE.REPORT_TUNING_TASK( 'my_sql_tuning_task') FROM DUAL;


删除优化task:

EXECDBMS_SQLTUNE.EXECUTE_TUNING_TASK('my_sql_tuning_task');

 

2.4   用sql profile替换执行计划

一个sql有多个执行计划时候,用一个好的执行计划替换差的执行计划。参见MOS文档Doc ID1400903.1,需要下载Oracle工具SQLT (详见215187.1)中的脚本,解压目录sqlt/utl/下脚本coe_load_sql_profile.sql 。


查询出sql语句的sql_id和执行计划的plan_hash_value

SQL>select sql_id ,plan_hash_value, sql_text from v$sql where sql_text like'%scott.emp%';

 

SQL_IDPLAN_HASH_VALUE    SQL_TEXT        

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

329d885bxvrcr 3045807146  select ename from scott.emp whereename='MILLER'

4f74t4ab7rd5y 2872589290  select *+ FULL (EMP) */ ename from scott.emp where ename='MILLER'

 

用sql语句4f74t4ab7rd5y执行计划2872589290  替换sql语句329d885bxvrcr的所有执行计划。执行coe_load_sql_profile.sql这个脚本的用户必须是非sys的dba用户,比如system用户。


SQL>connect system/pass

SQL> @coe_load_sql_profile.sql

Parameter 1:

ORIGINAL_SQL_ID (required)

Enter value for 1: 329d885bxvrcr

 

Parameter 2:

MODIFIED_SQL_ID (required)

Enter value for 2: 4f74t4ab7rd5y

 

    PLAN_HASH_VALUE         AVG_ET_SECS

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

          2872589290                 .003

 

Parameter 3:

PLAN_HASH_VALUE (required)

Enter value for 3: 2872589290 

Values passed tocoe_load_sql_profile:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ORIGINAL_SQL_ID:"329d885bxvrcr"

MODIFIED_SQL_ID:"4f74t4ab7rd5y"

PLAN_HASH_VALUE:"2872589290"

 

ORIGINAL:329D885BXVRCR MODIFIED:4F74T4AB7RD5Y PHV:2872589290 SIGNATURE:15822026218863957422 CREATED BYCOE_LOAD_SQL_PROFILE.SQL

SQL>SET ECHO OFF;

 

****************************************************************************

* Enter SCOTT password to exportstaging table STGTAB_SQLPROF_329d885bxvrcr

****************************************************************************

Export: Release 11.2.0.3.0 -Production on Sun Mar 11 14:45:47 2012

Copyright (c) 1982, 2011, Oracleand/or its affiliates.  All rightsreserved.

Password:

coe_load_sql_profile completed.


2.5  IO大的sql语句

问题描述:

在IO比较繁忙时候,查看数据库等待事件,比如db file sequential read等,wait_classs=’ User I/O’类的等待事件。

解决思路:

查看sql_id多的sql。根据这个sql_id查看session信息:

su - oracle

sqlplus as sysdba

SQL> select inst_id,

       Sql_id,

       event,

       count(1)

  fromgv$session

where wait_classs=’User I/O’

 group by inst_id,

       sid,

       event;


上面的语句多执行几次,如果在20秒内,这些并发量较大的sql的sid变化不大,那就查看个sql语句:

su - oracle

sqlplus / as sysdba

SQL> select inst_id,

       sid,

       event,

       sql_hash_value,

       ROW_WAIT_OBJ#,

       sql_id,

       blocking_session,

       blocking_instance

  from  gv$session

where Sql_id=’&sqlid’;

SQL> select SQL_FULLTEXT fromv$sqlarea where sql_id = '&sql_id';


并且分析这个sql语句的执行计划:

su - oracle

sqlplus / as sysdba

SELECT * FROMTABLE(dbms_xplan.display_awr('&sql_id'));

可以使用合理的索引,正确的统计信息,或者采用【2.1.3】和【2.1.4】中内容优化sql。


2.6   CPU使用率高的sql语句

问题描述:

有些sql语句消耗CPU,比如引起等待事件db files cattered read的sql语句,这是全表或全索引扫描引起的。

解决方法:

su - oracle

sqlplus / as sysdba

SQL> select inst_id,

       Sql_id,

       count(1)

  from gv$session

where event = 'db file scattered read'

 group by inst_id,sid;

查看sql_id多的sql。


根据这个sql_id查看session信息:

su - oracle

sqlplus / as sysdba

SQL> select inst_id,

       sid,

       event,

       sql_hash_value,

       ROW_WAIT_OBJ#,

       sql_id,

       blocking_session,

       blocking_instance

  fromgv$session

where Sql_id=’&sqlid’;

多执行几次,如果在20秒内,这些并发量较大的sql的sid变化不大,那就查看个sql语句

 

SQL> select SQL_FULLTEXT fromv$sqlarea where sql_id = '&sql_id';

并且分析这个sql语句的执行计划:

su - oracle

sqlplus / as sysdba

SQL>SELECT * FROMTABLE(dbms_xplan.display_awr('&sql_id'));

可以使用合理的索引,正确的统计信息,或者采用【2.1.3】和【2.1.4】中内容优化sql。


2.7   RAC数据库私有网卡流量大

问题描述:

RAC数据库私有网卡流量大时候,会影响数据库性能,一些sql语句会导致私有网卡流量大,这会引起gc类的等待事件。

解决方法:

查看sql_id多的sql。根据这个sql_id查看session信息:

su - oracle

sqlplus / as sysdba

SQL> select inst_id,

       Sql_id,

       count(1)

  fromgv$session

where event like 'gc%'

 group by inst_id,sid;

 

SQL> select inst_id,

       sid,

       event,

      sql_hash_value,

       ROW_WAIT_OBJ#,

       sql_id,

       blocking_session,

       blocking_instance

  fromgv$session

where Sql_id=’&sqlid’;

多执行几次,如果在20秒内,这些并发量较大的sql的sid变化不大,那就查看个sql语句

 

SQL> select SQL_FULLTEXT from v$sqlareawhere sql_id = '&sql_id';

并且分析这个sql语句的执行计划:

SQL>SELECT * FROMTABLE(dbms_xplan.display_awr('&sql_id'));

可以使用合理的索引,正确的统计信息,或者采用【2.1.3】和【2.1.4】中内容优化sql。


2.8  热点块等待事件

热点块是把数据库从数据文件复制到db buffer cache的等待。主要体现在等待事件latch: cache bufferschains或buffer busywaits。

解决思路:

su - oracle

sqlplus / as sysdba

SQL> select inst_id,

       Sql_id,

       count(1)

  fromgv$session

where event in ('latch:cache buffers chains', 'buffer busy waits')

 group by inst_id,

       sid;

查看sql_id多的sql。根据这个sql_id查看session信息:

su - oracle

sqlplus / as sysdba

SQL> select inst_id,

       sid,

       event,

       sql_hash_value,

       ROW_WAIT_OBJ#,

       sql_id,

       blocking_session,

       blocking_instance

  fromgv$session

where Sql_id=’&sqlid’;

多执行几次,如果在20秒内,这些并发量较大的sql的sid变化不大,那就查看个sql语句

su - oracle

sqlplus / as sysdba

SQL> select SQL_FULLTEXT fromv$sqlarea where sql_id = '&sql_id';

并且分析这个sql语句的执行计划:

su - oracle

sqlplus / as sysdba

SELECT * FROMTABLE(dbms_xplan.display_awr('&sql_id'));

可以使用合理的索引,正确的统计信息,或者采用【2.1.3】和【2.1.4】中内容优化sql。


2.9  根据等待事件找出相关sql和对象

解决思路:

su - oracle

sqlplus / as sysdba

SQL> select inst_id,

       sid,

       event,

       sql_hash_value,

       ROW_WAIT_OBJ#,

       sql_id,

       blocking_session,

       blocking_instance

  fromgv$session where event =  like 'event%');

找出被阻塞的sql_id,引起阻塞的对象ROW_WAIT_OBJ#(dba_objects.object_id).


查看被阻塞的sql

su - oracle

sqlplus / as sysdba

SQL> select SQL_FULLTEXT fromv$sqlarea where sql_id = '&sql_id';

 

查看引起阻塞的对象

su - oracle

sqlplus / as sysdba

SQL> Select owner,object_name,object_typefrom dba_objects where object_id=&oi;

 

 

2.10  library cache lock和cursor: pin

解决思路:


这两个等待事件多的情况下,首先看看参数sga_target是否为非0

su - oracle

SQL>sqlplus / as sysdba

SQL>show parameter sga_target

如果是非0,再看看发生问题时间段是否有sga自动调整

SQL>

select

 INST_ID     

 COMPONENT   

 OPER_TYPE   

 OPER_MODE   

 PARAMETER   

 INITIAL_SIZE

 TARGET_SIZE 

 FINAL_SIZE   

 STATUS      

 START_TIME  

 END_TIME    

Fromgv$sga_resize_ops;


如果在出现问题时间段(FINAL_SIZE-INITIAL_SIZE)值比较大,这说明sga自动调整影响了数据库性能。解决这个问题有两种方式,等待或者杀掉出问题的session。找出有问题sql语句参见【2.1.9】。事后,可以调整db_cache_size和shared_pool_size最大值,或者把sga_target设置为0。


文章转载自华创信科,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论