我有一个 Oracle 实例,其中有 user1、user2 和 user3 帐户。昨天我可以登录所有三个帐户。今天我可以登录 user1 和 user3,但 user2 却以某种我无法理解的方式完全“冻结”。
如果我尝试使用 sqlplus 登录到 user2,它就会一直旋转。它不会连接,不会超时,直到我按 CTRL+C 终止该进程,什么也不会发生。以 user1 或 user3 身份连接是即时的。
我想尝试锁定用户 2,然后尝试解锁。锁定用户的查询运行了 25 分钟,然后我放弃了!锁定用户 1 然后解锁用户 1 立即运行。
使用蟾蜍并以 DBA 身份进行连接后,我使用 Session Browser 进行调查。我发现以 user2 身份连接到数据库的 11 个连接。其中五个似乎是我使用 sqlplus 进行连接的失败尝试。这些连接均未显示任何打开的游标、当前语句或任何锁定。在等待选项卡上,10 个连接显示“行缓存锁定”,其中:
- 等待时间在 3,000 到 60,000 秒之间
- P1 = 7
- P1 Text = “缓存ID”
- P2 = 0
- P2 文本 = “模式”
- P3 = 3
- P3 文本 = “请求”
其中一个连接非常显眼,因为它看起来非常老旧。它显示了一条“来自客户端的 SQL*Net 消息”,其中包含:
- 等待秒数 > 600,000
- P1 = 1413697536
- P1 文本 = “驾驶员 ID”
- P2 = 1
- P2 文本 = “#bytes”
- P3 = 0
- P3 文本 = “”
我无法终止这 11 个会话中的任何一个。在我发出 kill 命令(使用 TOAD,带或不带立即选项)后,它会运行 45-60 秒,然后显示“会话已标记为终止。”但会话从未消失。
知道这意味着什么吗?或者我如何终止这些会话并恢复对 user2 帐户的访问权限?
更新:警报日志中有一些有趣的行:
2009 年 12 月 29 日星期二 09:37:45
警告:入站连接超时 (ORA-3136)
2009 年 12 月 29 日星期二 10:25:45 >>> 等待行缓存入队锁的时间过长!pid=37 系统状态已转储到跟踪文件 [snip]\udump\ora_2860.trc 2009 年 12 月 30 日星期三 11:55:59 orakill:尝试终止 tid=436 2009 年 12 月 30 日星期三 11:56:04 orakill:ssthreadkill(tid=436) 无法获取线程列表互斥锁:err=0
>>> WAITED TOO LONG FOR A ROW CACHE ENQUEUE LOCK! pid=17
System State dumped to trace file [snip]\udump\ora_1988.trc
Tue Dec 29 10:54:17 2009
WARNING: inbound connection timed out (ORA-3136)
Tue Dec 29 10:55:47 2009
WARNING: inbound connection timed out (ORA-3136)
Tue Dec 29 10:56:47 2009
WARNING: inbound connection timed out (ORA-3136)
Tue Dec 29 10:57:47 2009
WARNING: inbound connection timed out (ORA-3136)
Tue Dec 29 11:12:17 2009
WARNING: inbound connection timed out (ORA-3136)
Tue Dec 29 12:06:17 2009
WARNING: inbound connection timed out (ORA-3136)
Tue Dec 29 12:26:47 2009
WARNING: inbound connection timed out (ORA-3136)
Tue Dec 29 12:27:47 2009
WARNING: inbound connection timed out (ORA-3136)
Tue Dec 29 13:46:17 2009
WARNING: inbound connection timed out (ORA-3136)
Wed Dec 30 10:02:16 2009
解决:这似乎是 10.2.0.3 的一个错误,我需要重新启动实例,但我没有权限这样做,所以我将不得不等待几天。
答案1
请尝试以下操作:
select s.username, s.sid, p.spid
from v$session s join v$process p on addr=paddr
where s.username = 'USER2';
使用上述查询中的 spid 值,登录到服务器并从 DOS 命令提示符发出以下命令:
orakill YOURSID spid
YOURSID 是您正在处理的数据库实例的 SID。
当 GUI 工具无法终止进程时,orakill 通常会起作用。下面是一个orakill 的概述很好。请注意使用 orakill 的原因 #1 - 它也许可以解释为什么您不能使用 GUI 工具:
alter system 语句不会清除任何存在的锁。相反,会话将保持连接状态,直到超时,然后会话被终止,锁被释放。orakill 命令将立即终止线程和锁。
更新:
您还可以尝试:
select sid, serial#, program from v$session;
alter system kill session '<SID>,<SERIAL#>' immediate;
尽管我不会抱有太大的希望……