前几日,一套核心业务数据库待投产环境进行投产前测试时应用出现大量“Io 异常: Connection reset”报错,应用无法连接数据库。要来数据库相关信息后,登陆数据库检查状态发现数据库正处于大量’Library Cache Lock与Library Cache Mutex :X等待中,如下图ASH所示:
大量ddl_lock type为79,已经知晓了这种现象的根因,随手做了一个数据库systemstate dump进行验证:
oradebug setmypid oradebug dump systemstate 266; oradebug tracefile_name;
探寻 dump Trace文件,我们看到会话正在等待Library Cache Lock,做system dump 的意义在于,要找到持有Library Cache Handle Lock的会话为什么会持有锁,为什么不及时释放锁从而导致后续活动会话get不到Lock资源从而等待,
dump trace文件中已经明确显示了该handle address,继续搜寻后发现证实了我的猜测,
我们看到,该Hanlde Lock既有RequestMode=X,同时又存在LockMode=X ,不兼容从而发生的阻塞等待是正常现象,但是发现了该Library Cache Lock 的Namespace=ACCOUNT_STATUS(79),证实了我的猜测,该阻塞等待是因为数据库账户密码错误导致触发Oracle 延迟登录特性,从而产生大量Library Cache Lock。但是为何Io 异常: Connection reset呢?猜测是因为数据库活动会话大量积压,应用服务器连接数被撑满。
既然找到并且证实了根因,针对此问题下一步该如何操作?针对数据库账户密码错误,我们可以执行:
alter system set events '1017 trace name errorstack forever,level 3';
该errorstack会生成trace文件,在trace文件中确认,waitint for library cahce lock中的machine,也就是密码错误触发延迟登录长时间持有Library Cache Lock的应用服务器。
设置完成后,只要利用错误密码登录数据库抛出ORA-01017,则会在数据库Alert中产生一个Trace文件.
随后将报错应用服务器发送至应用方,检查配置的数据库账户密码是否正确。
最后, 为消除之后隐患,在数据库中执行
ALTER SYSTEM SET EVENTS '28401 TRACE NAME CONTEXT FOREVER, LEVEL 1' :
从而使得,今后会话在因密码登录失败后,直接返回报错,不会长时间持有LIBRARY CACHE LOCK 。