1.查看后台是否有锁:
SELECT sq.INST_ID,
SQ.SQL_TEXT, /*SQL文本*/
SE.SID, /*会话的唯一标识,通常要对某个会话进行分析前,首先就需要获得该会话的SID。*/
SE.BLOCKING_SESSION,
SQ.OPTIMIZER_COST AS COST_, /* COST 值*/
SE.LAST_CALL_ET CONTINUE_TIME, /*执行时间*/
SE.EVENT, /*等待事件*/
SE.LOCKWAIT, /*是否等待LOCK(SE,P)*/
SE.MACHINE, /*客户端的机器名。(WORKGROUP\PC-201211082055)*/
SQ.SQL_ID, /*SQL_ID*/
SE.USERNAME, /*创建该会话的用户名*/
SE.LOGON_TIME, /*登陆时间*/
'ALTER SYSTEM KILL SESSION ''' || SE.SID || ',' || SE.SERIAL# ||
''';' KILL --若存在锁情况,会用到KILL锁释放~
FROM gV$SESSION SE, /*会话信息。每一个连接到ORACLE数据库的会话都能在该视图中对应一条记录,根据该视图中的信息可以查询该会话使用的用户,正在执行或者刚刚执行的SQL语句*/
/**/
gV$SQLAREA SQ /*跟踪所有SHARED POOL中的共享CURSOR信息,包括 执行次数,逻辑读,物理读等*/
WHERE SE.SQL_HASH_VALUE = SQ.HASH_VALUE
AND SE.STATUS = 'ACTIVE'
AND SE.SQL_ID = SQ.SQL_ID
AND SE.USERNAME = SQ.PARSING_SCHEMA_NAME
--过滤条件
AND SE.USERNAME = 'FWSB' --用户名
and se.BLOCKING_SESSION is not null;

以下将重点的几个列说明一下
SQL_TEXT——被锁的语句;开发人员需要判断,这里面有没有反馈慢的功能对应的语句。
SID——被锁的语句对应的SID;
BLOCKING_SESSION——锁源头,如图所示,SID=510的语句导致SID=697的语句锁了;
CONTINUE_TIME——被锁的时间,单位为秒;
EVENT——被锁语句的等待事件,比如read by other session,gc buffer busy acquire, enq:TX – row lock contention这些,
特别强调,如果看到enq:TX – row lock contention,这个是我们平时所说的锁表,不同进程操作同一条数据。
MACHINE——被锁语句的机器名,我们系统功能对应的应该为feng 或者 tiao,否则不是我们系统的语句;
SQL_ID——被锁语句的SQL_ID;
如果慢的功能恰好在这里面被查出了,那么说明这个功能被锁了。
这时候可以考虑把导致功能被锁的语句发出来,让其他开发人员确认一下对应功能。然后跟客户或者运维同事反馈一下。
但是如果慢的功能没有在这里面查出来,那需要按照接下来的流程处理了,有点繁琐,但目前我这边还没有什么更好的方法。如果大家有,可以拿出来交流分享一下。
2.定位功能对应的语句

首先打开PLSQL,调出SESSION窗口,选择上面的选择框为ACTIVE SESSIONS 即正在执行中的进程。
然后查一下,当前执行的SESSION中,是否有慢的功能对应的语句,在“SQL文本”那个页签里面查找,
如果觉得这个页签展示的信息不足以帮助确定功能,可以选择切换到“锁”的页签,看到里面有OBJECT_NAME列,里面有功能涉及到的表名。C_TIME列有这个功能执行了多少秒,大体可以推测出功能是什么时间点触发的。通过表名、时间,大概能判断出是什么功能。如果通过这些还找不到,那可能需要找找别的原因了。如果一个开发人员表示自己也不清楚功能涉及到什么表,那我表示我已经无能为力了……
通过上面截图的语句大概可以看出,这个进程跑的应该是全国业务,因为涉及到交互订单项表和账单表。但是具体业务功能,那需要全国模块相关开发人员通过进程对应的语句具体分析了。(我这里只是随便找了个语句举例说明。)

有的时候,我们通过这种方式找到了慢的语句,但是粘贴出来发现有的地方是用‘冒号+数字’的形式展示的,这表示该处的参数使用了绑定变量。

此时,找到语句对应的SQL_ID,如图所示,通过以下脚本查询对应的绑定变量是多少
SELECT SQL_ID, NAME, DATATYPE_STRING, LAST_CAPTURED, VALUE_STRING
FROM GV$SQL_BIND_CAPTURE
WHERE SQL_ID = '00fb2hc1psmrb'
ORDER BY LAST_CAPTURED DESC, POSITION;
--在出问题的实例上执行,请自行替换SQL_ID,此时该SQL还在SHARED POOL中,没有被AGED OUT
SELECT INSTANCE_NUMBER,
SQL_ID,
NAME,
DATATYPE_STRING,
LAST_CAPTURED,
VALUE_STRING
FROM DBA_HIST_SQLBIND
WHERE SQL_ID = '00fb2hc1psmrb'
ORDER BY LAST_CAPTURED DESC, POSITION;
--请自行替换SQL_ID,此时是从AWR中查询。

将语句中的B1 B2分别替换结果中的,B1 B2;
需要注意的是,一定要对应要参数后面的时间与语句执行的时间是否相同,如果不同说明当时语句执行时,并不是使用该组参数。
如果第一个语句查不到结果,那么可以尝试一下第二个语句。
因为数据库存储的记录数量有限,如果这种两个都无法找到你想找的对应时间点的参数,那就只能放弃了。
最后总结一下处理流程:
1. 先查是否被锁;
2. 如果被锁,则找源头开发人员确认;如果没有被锁,查后台是否有功能对应的进程;