在日常工作中经常接收到各类升级问题。其中较为常见的问题就是在编译存储过程时一直卡住无法继续的问题。这类问题一般多是由于发生了阻塞。如果升级过程中没有完全切断客户端对数据库的连接。例如仍然有用户在操作相关过程或者数据库JOB在自动化的执行等都可能导致存储过程编译被阻塞进而导致无法完成升级。这时只有等待相关会话执行完毕或者杀掉会话才能继续升级。如果升级中出现以下错误那么必然是发生了阻塞。
针对卡住的问题,也可以通过查询V$SESSION视图来提前发现并进行解决。考虑到客户可能使用的是RAC模式,所以查询都从GV$SESSION视图查询,该视图会显示所有实例的数据。使用SQL查询时必须确保存储过程还处于编译的活动状态。相关SQL如下所示:
SELECT T.MODULE,
T.INST_ID,
T.SID,
T.EVENT,
T.BLOCKING_INSTANCE,
T.BLOCKING_SESSION,
T.BLOCKING_SESSION_STATUS,
T.MACHINE,
T.OSUSER,
T.SQL_ID,
(SELECT X.SQL_TEXT
FROM GV$SQL X
WHERE X.INST_ID = T.INST_ID
AND T.SQL_ID = X.SQL_ID
AND ROWNUM = 1) SQL_TEXT,
T.*
FROM GV$SESSION T
WHERE USERNAME IS NOT NULL
AND STATUS = 'ACTIVE'
ORDER BY LOGON_TIME, T.SID
查询结果如下:
在上图中 SID为223的会话很明显的被阻塞了。因为它的EVENT是library cache pin这意味着Oracle内部锁可能存在阻塞。由于
BLOCKING_SESSION=222,
BLOCKING_INSTANCE=1,
BLOCKING_SESSION_STATUS=VALID
这三个字段都有值,且状态为VALID。所以通过以上数据可以得出以下结论:当前实例1上SID为223会话已经被实例1上的222会话阻塞了,所以SID为223的会话如果要继续执行下去就必须等待实例1上的SID为222的会话执行完毕或者杀掉会话才行。
如果确定要杀掉会话,那么需要登录到阻塞会话所在的机器上进行操作(RAC模式必然由两台以上数据库服务器组成)在本例中需要登录实例1所对应的机器并执行以下命令
ALTER SYSTEM KILL SESSION 'sid,serial#';
SID和SERIAL#都是GV$SESSION上查询出的字段。在本例中替换后为
ALTER SYSTEM KILL SESSION '222,2178';