欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

某个普通用户登录一直hang住,不报错。library cache lock等待

程序员文章站 2022-05-08 23:02:24
故障描述用某个用户登录数据库,一直hang住,不报错于是直接尝试用sqlplus连接数据库,发现连接该用户时hang在那里,过很久之后会返回ORA-04021错误,但是别的用户都没问题。SQL> conn pingshen/pingshencsERROR:ORA-04021: 等待锁定对象 时发生超时警告: 您不再连接到 ORACLE。问题排查与解决通过检查等待事件,发现是library cache lock并且发现,除了登录进程,还有一大堆的已经登录的进程被阻塞在libra...

故障描述

用某个用户登录数据库,一直hang住,不报错

于是直接尝试用sqlplus连接数据库,发现连接该用户时hang在那里,过很久之后会返回ORA-04021错误,但是别的用户都没问题。

SQL> conn pingshen/pingshencs
ERROR:
ORA-04021: 等待锁定对象  时发生超时


警告: 您不再连接到 ORACLE。

问题排查与解决

通过检查等待事件,发现是library cache lock
并且发现,除了登录进程,还有一大堆的已经登录的进程被阻塞在library cache lock.

经过测试,这个问题只发生在一个用户上,使用这个用户登录需要等待很长时间才会返回登录失败的信息,而使用其他的用户登录则不存在问题。

通过V$SESSION_WAIT视图,可以看到对应的等待事件:

SQL> select sid,event from v$session_wait;

V$SESSION_WAIT中查找有问题的wait

SQL> select event,count(*) from v$session_wait group by event;

EVENT                                                              COUNT(*)
---------------------------------------------------------------- ----------
SQL*Net message from client                                             125
rdbms ipc message                                                        12
smon timer                                                                1
pmon timer                                                                1
library cache lock                                                       97
Streams AQ: qmn slave idle wait                                           1
Space Manager: slave idle wait                                            1
SQL*Net message to client                                                 1
Streams AQ: qmn coordinator idle wait                                     1
VKTM Logical Idle Wait                                                    1
Streams AQ: waiting for time management or cleanup tasks                  1
DIAG idle wait                                                            2

已选择12行。
SQL> select distinct kglhdbsp,kglhdnsd from x$kglob;

  KGLHDBSP KGLHDNSD
---------- ----------------------------------------------------------------
         0 SQL AREA BUILD
         0 SQL AREA
         0 BODY
         1 ACCOUNT_STATUS
        15 SCHEMA
        30 SQL AREA
         0 SCHEDULER EARLIEST START TIME
        19 SQL AREA
        17 ACCOUNT_STATUS
      1188 ACCOUNT_STATUS
         0 SCHEDULER GLOBAL ATTRIBUTE
         0 DBLINK
         0 SQL AREA STATS
         0 INDEX
        32 SQL AREA
         0 QUEUE
         1 BODY
         0 DBINSTANCE
         0 JAVA DATA
        20 SQL AREA
         0 RESOURCE MANAGER
        12 TRIGGER
        14 PUB SUB INTERNAL INFORMATION
         0 SUBSCRIPTION
         0 JAVA RESOURCE
       100 SQL AREA STATS
         0 RULE EVALUATION CONTEXT
         1 PUB SUB INTERNAL INFORMATION
         0 TABLE/PROCEDURE
         0 SCHEMA
         0 CLUSTER
         1 TRIGGER
         0 PUB SUB INTERNAL INFORMATION
        54 SQL AREA
       100 TABLE/PROCEDURE
        34 SQL AREA
         2 SQL AREA
         0 JAVA SOURCE
       100 SQL AREA
         1 SCHEMA
         1 SQL AREA STATS
        85 SQL AREA
         0 TRIGGER
         3 PUB SUB INTERNAL INFORMATION
         0 RULESET
         0 MULTI-VERSION OBJECT FOR INDEX
        36 EDITION
         0 MULTI-VERSION OBJECT FOR TABLE

已选择48行。

ACCOUNT_STATUS说明library cache lock是在account上,很可能是用错误的用户名密码登录,或者正有人alter user(这种可能很小)

通过对DBA_HIST_ACTIVE_SESS_HISTORY的分析,发现大量等待library cache lock的会话都是JDBC Thin Client引起的,并且是user_id为116,也就是这个登录不上的这个账号,且这些会话的状态都是在IN_CONNECTION_MGMT为Y的阶段,换句话来说,也就是会话连接初始创建的一个阶段。

SQL> select SAMPLE_TIME,USER_ID,EVENT,TOP_LEVEL_CALL_NAME,IN_CONNECTION_MGMT,PROGRAM
from DBA_HIST_ACTIVE_SESS_HISTORY
where event='library cache lock';

某个普通用户登录一直hang住,不报错。library cache lock等待
某个普通用户登录一直hang住,不报错。library cache lock等待

而且此时还发现一个现象,就是利用这个用户登录时,即使用户名的密码输入错误,sqlplus也会等待很长时间,然后才会返回错误信息。而这个长时间的等待从V$SESSION视图中查询,恰恰就是library cache lock等待事件。
上面的两个现象说明,library cache lock的等待实际上是发生在用户登录之前的。其实从数据库V$SESSION视图中也可以看出这个问题:

SQL> SELECT sid, username, event,seconds_in_wait
FROM gv$session
WHERE event = 'library cache lock';

某个普通用户登录一直hang住,不报错。library cache lock等待
某个普通用户登录一直hang住,不报错。library cache lock等待

可以看到,所有出现library cache lock等待的会话用户名都是空。这些会话并不是Oracle后台进程,而是刚才提到的问题用户,这同样说明当方式这个library cache lock等待时,会话还没有成功的登录到数据库中。

那么现在问题有点棘手,如果会话没有登录,则没有办法检查会话执行了哪些操作,Oracle的文档中也没有提到过,会话登录之前会进行哪些操作,经历哪些等待。
分析一下这个问题,整个数据库目前只有这个用户出现了library cache lock的等待,而其他用户没有出现,说明问题肯定和这个用户的自身特点有关。
通过登录触发器设置TRACE后发现,会话登录后并无任何异常操作,且TRACE文件中看不到library cache lock等待信息。而且即使用户名密码错误,也会出现这个等待事件。这说明等待发生在登录之前,与用户登录后的行为无关。

首先检查了DBA_PROFILES,确认和密码以及登录有关的PROFILE是否存在限制,当前数据库已经都设置为UNLIMITED,那么问题应该和PROFILE无关。

SQL> select * from dba_profiles where profile='DEFAULT';

PROFILE                        RESOURCE_NAME                    RESOURCE LIMIT
------------------------------ -------------------------------- -------- ----------------------------------------
DEFAULT                        COMPOSITE_LIMIT                  KERNEL   UNLIMITED
DEFAULT                        SESSIONS_PER_USER                KERNEL   UNLIMITED
DEFAULT                        CPU_PER_SESSION                  KERNEL   UNLIMITED
DEFAULT                        CPU_PER_CALL                     KERNEL   UNLIMITED
DEFAULT                        LOGICAL_READS_PER_SESSION        KERNEL   UNLIMITED
DEFAULT                        LOGICAL_READS_PER_CALL           KERNEL   UNLIMITED
DEFAULT                        IDLE_TIME                        KERNEL   UNLIMITED
DEFAULT                        CONNECT_TIME                     KERNEL   UNLIMITED
DEFAULT                        PRIVATE_SGA                      KERNEL   UNLIMITED
DEFAULT                        FAILED_LOGIN_ATTEMPTS            PASSWORD UNLIMITED	# 设置的是unlimited
DEFAULT                        PASSWORD_LIFE_TIME               PASSWORD UNLIMITED
DEFAULT                        PASSWORD_REUSE_TIME              PASSWORD UNLIMITED
DEFAULT                        PASSWORD_REUSE_MAX               PASSWORD UNLIMITED
DEFAULT                        PASSWORD_VERIFY_FUNCTION         PASSWORD NULL
DEFAULT                        PASSWORD_LOCK_TIME               PASSWORD UNLIMITED
DEFAULT                        PASSWORD_GRACE_TIME              PASSWORD UNLIMITED

已选择16行。

简单总结一下,问题和当前用户的自身特性有关,且与DBA_PROFILE无关,也与用户登录后的行为无关。如果不考虑PROFILE,那么用户特有的属性恐怕就剩下了用户名和密码了。而且在一次成功的登录数据库后,这个现象曾短时间消失,这说明问题可能确实和密码有关系。
在11g中,Oracle的密码策略确实出现了一些改变,比如密码变成大小写敏感。这个问题很可能导致老的程序来连接数据库时出现密码错误的现象。此外,11g还新增了一个密码相关的特性——密码错误延迟验证:当用户连续的输入错误的密码,Oracle所需要的密码验证时间会逐步增加,这可以有效的避免有人试图通过暴力方式来破解密码。关于11g新增密码错误延迟验证的详细内容,可以参考:http://yangtingkun.itpub.net/post/468/505041
那么当前的问题和这个密码延迟验证有关系吗,如果是密码延迟验证的问题,那么至少要多次重复输入错误的密码。不过从刚才的V$SESSION视图中可以看到,问题用户存在多个会话在登录数据库,如果是程序连接数据库,且配置了错误的密码,那么基本上就可以确定问题了。
询问了相关程序人员,发现一个测试程序的密码确实配置错误,且这个程序目前仍然在后台不断的尝试连接数据库。
现在所有的疑问都解开了,用户程序已错误的密码不断登录,在加上11g的密码延迟验证,使得用户的验证等待时间不断加长。这也解释了为什么输入正确的密码登录后,这个现象曾短暂消失,因为用户成功登录,密码延迟验证的时间归零。
找到问题的原因后,在客户的数据库上以其他的用户尝试模拟这个现象,测试发现,如果一个会话登录数据库,即使每次密码都不正确使得延迟验证时间不断变长,也不会引发library cache lock的等待时间,但是只要该用户存在第二个登录会话,这时library cache lock会在两个会话同时出现,而且即使这个会话尝试使用正确的密码登录,在成功登录之前,也要等待library cache lock事件。
根据这个现象,个人推测Oracle为了实现延迟验证,必然需要在共享池中保存一个类似计数器的对象。这个计数器记录用户登录连续密码错误次数,从而确定延迟验证的等待时间。当用户成功登录,计数器清零。如果是一个会话,那么只需要独占这个计数器就可以了,当存在两个以上的会话,且两个会话都试图修改计数器的内容,那么资源竞争就出现了,而体现在数据库中的等待事件就是library cache lock。当然这只是个人的猜测而已,还没有看到Oracle官方对这种情况的说明。

问题解决

最后重启数据库,并且修改登录到Oracle 数据库时可以失败的次数FAILED_LOGIN_ATTEMPTS

SQL> alter profile default limit FAILED_LOGIN_ATTEMPTS 10;

配置文件已更改

SQL> select * from dba_profiles where profile='DEFAULT';

PROFILE                        RESOURCE_NAME                    RESOURCE LIMIT
------------------------------ -------------------------------- -------- ----------------------------------------
DEFAULT                        COMPOSITE_LIMIT                  KERNEL   UNLIMITED
DEFAULT                        SESSIONS_PER_USER                KERNEL   UNLIMITED
DEFAULT                        CPU_PER_SESSION                  KERNEL   UNLIMITED
DEFAULT                        CPU_PER_CALL                     KERNEL   UNLIMITED
DEFAULT                        LOGICAL_READS_PER_SESSION        KERNEL   UNLIMITED
DEFAULT                        LOGICAL_READS_PER_CALL           KERNEL   UNLIMITED
DEFAULT                        IDLE_TIME                        KERNEL   UNLIMITED
DEFAULT                        CONNECT_TIME                     KERNEL   UNLIMITED
DEFAULT                        PRIVATE_SGA                      KERNEL   UNLIMITED
DEFAULT                        FAILED_LOGIN_ATTEMPTS            PASSWORD 10
DEFAULT                        PASSWORD_LIFE_TIME               PASSWORD UNLIMITED
DEFAULT                        PASSWORD_REUSE_TIME              PASSWORD UNLIMITED
DEFAULT                        PASSWORD_REUSE_MAX               PASSWORD UNLIMITED
DEFAULT                        PASSWORD_VERIFY_FUNCTION         PASSWORD NULL
DEFAULT                        PASSWORD_LOCK_TIME               PASSWORD UNLIMITED
DEFAULT                        PASSWORD_GRACE_TIME              PASSWORD UNLIMITED

已选择16行。

某个普通用户登录一直hang住,不报错。library cache lock等待

小插曲:

但是业务那边的应用并没有全部关掉,所以改完FAILED_LOGIN_ATTEMPTS以后,应用一直在频繁的尝试登录,账户会瞬间锁死。只能解锁,但是解锁后改密码的时间很长,要很久才会修改成功,但是这个账户依然没法连接。连接的时间非常长,最后依然是返回ORA-04021: 等待锁定对象 时发生超时 错误

后来又调整FAILED_LOGIN_ATTEMPTS为unlimited后,导致v$session_wait中的’library cache lock’event非常多:
某个普通用户登录一直hang住,不报错。library cache lock等待
最后发现,业务人员并没有把所有应用都关掉!
全部关掉后,恢复正常。

SQL> select username,account_status from dba_users
where username='PINGSHEN';  2

USERNAME                       ACCOUNT_STATUS
------------------------------ --------------------------------
XX                       OPEN

SQL> select count(*) from v$session_wait where event='library cache lock';

  COUNT(*)
----------
         0

SQL> conn XX/XX
已连接。

参考:
数据库登录出现library cache lock等待(一)

11.2数据库登录出现library cache lock等待(二)

一个library cache lock的问题

几种常见的library cache lock产生的原因

一次LIBRARY CACHE LOCK的处理

本文地址:https://blog.csdn.net/shayuwei/article/details/107638422

相关标签: 笔记 Oracle