一、背景:
某产品升级脚本报错
‘and i am waiting very much time and now see a error’
SQL>@upgrade.sql Porcedure created. PL/SQL procedure successfully completed Procedure created. Procedure dropped. Table truncated. Index created. Table created. 1 row craeted. Commit complete. Function created. CREATE OR REPLACE PROCEDURE update_onlineuser(lasttime in varchar2,segname in varchar2,tablename varchar2) * ERROR at line 1: ORA-04021:timeout occurred while waiting to lock object Procedure created. PL/SQL produre successfully completed. |
二、分析:
ORA-04021:等待锁定对象时发生超时
脚本里含有create or replace procedure,如果存储过程正在执行就会发生这种情况。而业务存储过程是oracle的job定时调用的(每10秒)(不知道是否由于存储过程执行时间超过10s造成存储过程一直执行而导致脚本执行等待超时?)所以执行脚本前要先停止job,并且要停止正在执行的存储过程或函数。
三、解决办法:
1. 以DBA用户登陆数据库,在数据库执行以下语句,为了job不执行,以免后面的执行脚本失败
-->查看job_queue_processes参数的值
SQL> show parameter job;
SQL>alter system set job_queue_processes=0;
2. 查询是否有正在执行的函数或存储过程,所致对象锁
SQL>select name
from v$db_object_cache
where owner='WISGDB'
and type in('PROCEDURE','FUNCTION')
and locks > 0
adn pins > 0;
如果能查询出记录,说明有存储过程或函数在执行,需要等待存储过程自己结束或者手工停止。
3. 手工停止正在执行的存储过程(第二部如果没有结果不需要执行此步骤)
SQL>select sid,serial#,status
from v$session a
where a.sid in (select sid
from v$access
where owner='WISGDB'
and OBJECT in (select name
from v$db_objuect_cache
where owner='WISGDB'
and type in ('PROCEDURE','FUNCTION')
and locks > 0
and pins > 0));
需要使用一下sql手工停止,用每一条记录的SID,SERIAL字段值代替下面sql的SID与SERIAL#字样
SQL>alter system kill session 'sid,serial#';
4.在wisgdb用户下执行xxx数据库脚本(执行前需确保第二部的SQL查询结果为空)
5. 以DBA用户登陆数据库,恢复JOB
SQL>alter system set job_queue_processes=20;(与之前保持一致)