Oracle包被锁定的原因分析及解决方案
在数据库的开发过程中,经常碰到包、存储过程、函数无法编译或编译时会导致PL/SQL 无法响应的问题。碰到这种问题,基本上都要重启数据库解决,严重浪费开发时间。本文将就产生这种现象的原因和解决方案做基本的介绍。
- 问题分析
从事数据库开发的都知道锁的概念,如:执行 Update Table xxx Where xxx 的时候就会产生锁。这种常见的锁在Oracle里面被称为DML锁。在Oracle中还有一种DDL锁,主要用来保证存储过程、表结构、视图、包等数据库对象的完整性,这种锁的信息可以在DBA_DDL_LOCKS中查到。注意:V$LOCKED_OBJECT记录的是DML锁信息,DDL锁的信息不在里面。
对应DDL锁的是DDL语句,DDL语句全称数据定义语句(Data Define Language)。用于定义数据的结构或Schema,如:CREATE、ALTER、DROP、TRUNCATE、COMMENT、RENAME。当我们在执行某个存储过程、或者编译它的时候Oracle会自动给这个对象加上DDL锁,同时也会对这个存储过程所引用的对象加锁。
了解了以上知识以后,我们可以得出结论:编译包长时间无响应说明产生了死锁。我们可以轻易的让这种死锁发生,举例:
1、
2、
3、
4、
5、
在Oracle中DDL锁分为:Exclusive DDL Locks(排他的DDL)、Share DDL Locks(共享DDL锁)、Breakable Parse Locks(可被打破的解析锁)几类。篇幅所限,这里就不再详细介绍了。根据这个例子推理一下,当我们试图编译、修改存储过程、函数、包等对数据对象的时候,如果别人也正在编译或修改他们时就会产生锁等待;或者我们在编译某个存储过程的时候,如果它所引用的数据库对象正在被修改应该也会产生锁等待。这种假设有兴趣的兄弟可以测试下,不过比较困难。
- 解决方案
碰到这种问题,如果知道是被谁锁定了(可以查出来的),可以让对方尽快把锁释放掉;实在查不出来只能手工将这个锁杀掉了。步骤如下:
1、
Select b.SID,b.SERIAL#
2、
3、
Select spid, osuser, s.program
4、
#kill -9 spid(UNIX平台)
orakill sid thread(Windows平台SID是Oracle的实例名,thread是上面查出来的SID)
5、
本文只能是说对这个问题做了初步分析,产生此问题的原因及解决方案涉及到很多Oracle的基本知识。如:DML语句,DDL语句;Oracle锁的机制;v$session 与 v$process之间关系等。有兴趣的兄弟可以更加深入的研究,欢迎跟我交流!