概述
在使用Oracle数据库时,遇到过ORA-4025错误,导致程序使用时发生错误。
ORA-4025错误虽然不是很常见的错误,却对我们理解数据库有一定的意义。
首先,让我们看一下这个错误的一般定义:
$ oerr ora 4025
04025, 00000, "maximum allowed library object lock allocated for %s%s%s%s%s"
// *Cause: Too many active locks for the object has been allocated. This error
// can be a result of too many cursors kept open per session.
// *Action: Close cursors, reduce session_cached_cursors value.
根据上面的描述,我们知道ORA-4025错误,通常可能由于打开的游标太多,导致某个库缓存对象上,加载的active locks 太多,因为library object lock的分配数量达到了上限时发生错误。
一般可以通过关闭游标或者 减少session_cached_cursors的值缓解这个问题。
以下是针对该错误描述的一些疑问:
1.Active lock是什么?什么时候会导致Active lock增多?
2.为什么减少参数session_cached_cursors的设定值能够缓解这个问题?
关于Active lock的增加原因
通常来讲,Active lock是Oracle数据库针对游标等库缓存对象(library cache object)分配的锁。
一般情况下对同一个对象,同时利用数增加时,Active lock数也会增加。
例如:
每一个打开的游标都会持有一个Active lock;有多个会话都同时利用某个游标(Cursor)时,打开的游标(open cursor)会增加,相应地Active lock也会增加。
下面我们看一个简单的说明Active lock增加的例子:
1.首先,我们在一个Session1中,执行某条SQL文:
--会话1
SQL> conn scott/tiger
Connected.
SQL> select count(*) from emp;
COUNT(*)
----------
14
然后,取一下System state dump.
SQL> conn /as sysdba
Connected.
SQL> alter session set tracefile_identifier='1session';
Session altered.
SQL> alter session set events 'immediate trace name systemstate level 266';
Session altered.
我们查看生成的System state dump关于这个游标相关的信息:
LibraryObjectLock: Address=0x8932bf98 Handle=0x891f6e58 Mode=N CanBeBrokenCount=1 Incarnation=1 ExecutionCount=1
User=0x9148c980 Session=0x9148c980 ReferenceCount=1 Flags=CNB/[0001] SavepointNum=579c0218
LibraryHandle: Address=0x891f6e58 Hash=88cd1004 LockMode=N PinMode=0 LoadLockMode=0 Status=VALD
ObjectName: Name=select count(*) from emp ★★★库缓存对象
FullHashValue=890202cf4a2f38d1f2a77f1688cd1004 Namespace=SQL AREA(00) Type=CURSOR(00) Identifier=2295140356 OwnerIdn=83
Statistics: InvalidationCount=0 ExecutionCount=1 LoadCount=2 ActiveLocks=1 TotalLockCount=1 TotalPinCount=1 ★★★★ActiveLocks
Counters: BrokenCount=1 RevocablePointer=1 KeepDependency=1 Version=0 BucketInUse=0 HandleInUse=0 HandleReferenceCount=0
Concurrency: DependencyMutex=0x891f6f08(0, 1, 0, 0) Mutex=0x891f6f98(0, 20, 0, 0)
Flags=RON/PIN/TIM/PN0/DBN/[10012841]
WaitersLists:
Lock=0x891f6ee8[0x891f6ee8,0x891f6ee8]
Pin=0x891f6ec8[0x891f6ec8,0x891f6ec8]
LoadLock=0x891f6f40[0x891f6f40,0x891f6f40]
Timestamp: Current=07-30-2016 10:25:44
HandleReference: Address=0x891f7020 Handle=(nil) Flags=[00]
LibraryObject: Address=0x875fe040 HeapMask=0000-0001-0001-0000 Flags=EXS[0000] Flags2=[0000] PublicFlags=[0000]
ChildTable: size='16'
Child: id='0' Table=0x875feef0 Reference=0x875fe930 Handle=0x8903f8a0
NamespaceDump:
Parent Cursor: sql_id=g59vz2u4cu404 parent=0x875fe0e0 maxchild=1 plk=y ppn=n
我们可以看到此时,对于【ObjectName: Name=select count(*) from emp 】这个对象的Active lock为1
Statistics: InvalidationCount=0 ExecutionCount=1 LoadCount=2 ActiveLocks=1★
2.我们接着在其他的会话中执行相同的SQL。
SQL> conn scott/tiger
Connected.
SQL> select count(*) from emp;
COUNT(*)
----------
14
并再次取得System state dump.
SQL> conn /as sysdba
Connected.
SQL> alter session set tracefile_identifier='2session';
Session altered.
SQL> alter session set events 'immediate trace name systemstate level 266';
Session altered.
我们查看生成的System state dump关于这个游标相关的信息:
LibraryObjectLock: Address=0x8932bf98 Handle=0x891f6e58 Mode=N CanBeBrokenCount=1 Incarnation=1 ExecutionCount=1
User=0x9148c980 Session=0x9148c980 ReferenceCount=1 Flags=CNB/[0001] SavepointNum=579c0218
LibraryHandle: Address=0x891f6e58 Hash=88cd1004 LockMode=N PinMode=0 LoadLockMode=0 Status=VALD
ObjectName: Name=select count(*) from emp ★★★★
FullHashValue=890202cf4a2f38d1f2a77f1688cd1004 Namespace=SQL AREA(00) Type=CURSOR(00) Identifier=2295140356 OwnerIdn=83
Statistics: InvalidationCount=0 ExecutionCount=2 LoadCount=2 ActiveLocks=2 TotalLockCount=2 TotalPinCount=1 ★★★★
Counters: BrokenCount=1 RevocablePointer=1 KeepDependency=1 Version=0 BucketInUse=1 HandleInUse=1 HandleReferenceCount=0
Concurrency: DependencyMutex=0x891f6f08(0, 1, 0, 0) Mutex=0x891f6f98(0, 24, 0, 0)
Flags=RON/PIN/TIM/PN0/DBN/[10012841]
WaitersLists:
Lock=0x891f6ee8[0x891f6ee8,0x891f6ee8]
Pin=0x891f6ec8[0x891f6ec8,0x891f6ec8]
LoadLock=0x891f6f40[0x891f6f40,0x891f6f40]
Timestamp: Current=07-30-2016 10:25:44
HandleReference: Address=0x891f7020 Handle=(nil) Flags=[00]
LibraryObject: Address=0x875fe040 HeapMask=0000-0001-0001-0000 Flags=EXS[0000] Flags2=[0000] PublicFlags=[0000]
ChildTable: size='16'
Child: id='0' Table=0x875feef0 Reference=0x875fe930 Handle=0x8903f8a0
NamespaceDump:
Parent Cursor: sql_id=g59vz2u4cu404 parent=0x875fe0e0 maxchild=1 plk=y ppn=n
...
LibraryObjectLock: Address=0x91eb8338 Handle=0x891f6e58 Mode=N CanBeBrokenCount=1 Incarnation=1 ExecutionCount=1
User=0x91aad100 Session=0x91aad100 ReferenceCount=1 Flags=CNB/[0001] SavepointNum=579c041e
LibraryHandle: Address=0x891f6e58 Hash=88cd1004 LockMode=N PinMode=0 LoadLockMode=0 Status=VALD
ObjectName: Name=select count(*) from emp ★★★★
FullHashValue=890202cf4a2f38d1f2a77f1688cd1004 Namespace=SQL AREA(00) Type=CURSOR(00) Identifier=2295140356 OwnerIdn=83
Statistics: InvalidationCount=0 ExecutionCount=2 LoadCount=2 ActiveLocks=2 TotalLockCount=2 TotalPinCount=1 ★★★★
Counters: BrokenCount=1 RevocablePointer=1 KeepDependency=1 Version=0 BucketInUse=1 HandleInUse=1 HandleReferenceCount=0
Concurrency: DependencyMutex=0x891f6f08(0, 1, 0, 0) Mutex=0x891f6f98(0, 24, 0, 0)
Flags=RON/PIN/TIM/PN0/DBN/[10012841]
WaitersLists:
Lock=0x891f6ee8[0x891f6ee8,0x891f6ee8]
Pin=0x891f6ec8[0x891f6ec8,0x891f6ec8]
LoadLock=0x891f6f40[0x891f6f40,0x891f6f40]
Timestamp: Current=07-30-2016 10:25:44
HandleReference: Address=0x891f7020 Handle=(nil) Flags=[00]
LibraryObject: Address=0x875fe040 HeapMask=0000-0001-0001-0000 Flags=EXS[0000] Flags2=[0000] PublicFlags=[0000]
ChildTable: size='16'
Child: id='0' Table=0x875feef0 Reference=0x875fe930 Handle=0x8903f8a0
NamespaceDump:
Parent Cursor: sql_id=g59vz2u4cu404 parent=0x875fe0e0 maxchild=1 plk=y ppn=n
我们可以看到此时,对于【ObjectName: Name=select count(*) from emp 】这个对象的Active lock为2
由于被不同的会话持有相同的游标对象,所以Active lock增加了。
Statistics: InvalidationCount=0 ExecutionCount=2 LoadCount=2 ActiveLocks=2 ★
另外,除了上面正常原因(如不同会话持有,不同子游标等)的影响以外,根据过去的经验,由于以下的原因,也可能导致Active lock的异常增加:
・数据库的Bug影响
・应用程序的问题,如应用程序中不断地打开游标却从来不进行游标关闭清理。
关于Active lock的上限
Active lock的上限通常为65536个。
session_cached_cursors作为解决方法的原因
为什么减少参数session_cached_cursors的设定值能够缓解这个问题?
首先,对于每一个打开的游标都会对相应的对象上持有一个Active lock;
参数SESSION_CACHED_CURSORS用来控制在每个会话中能够缓存的游标个数。
当SQL执行时,在客户端的内存中会保持的游标信息会在游标关闭时被清理。但是在Oracle中,通过SESSION_CACHED_CURSORS参数能够保存一定数量的游标信息不被关闭和清理。
因此,当减少参数session_cached_cursors的设定值时,能够使每个会话的客户端中保持的游标数减少,从而在某种程度上,降低了同一个游标的打开会话个数。
因此,减少参数session_cached_cursors的设定值能够缓解这个问题,减少ORA-04025错误的发生。
版权声明:本文为博主原创文章,转载必须注明出处,本人保留一切相关权力!http://blog.csdn.net/lukeunique
欢迎关注微信订阅号:TeacherWhat
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/141625.html