游乐游手机版
首页/数据库/文章详情

Oracle RAC如何清理无效的数据库连接?调整SQLNET超时

时间:2026-04-23 19:15
ORA-03113 ORA-03137幽灵会话因SQL*Net未探测断连而残留ACTIVE状态,需配置SQLNET EXPIRE_TIME、TCP CONNECT_TIMEOUT等参数并统一RAC各节点,必要时kill -9 SPID强制清理。 ORA-03113 ORA-03137:连接断开后会话

ORA-03113/ORA-03137幽灵会话因SQL*Net未探测断连而残留ACTIVE状态,需配置SQLNET.EXPIRE_TIME、TCP.CONNECT_TIMEOUT等参数并统一RAC各节点,必要时kill -9 SPID强制清理。

ORA-03113/ORA-03137:连接断开后会话仍卡在ACTIVE状态

在Oracle RAC环境中,一个颇为恼人的现象是:客户端因为网络闪断、应用崩溃或者防火墙策略清理空闲连接而异常断开后,数据库的v$session视图里,却常常残留着一大批状态显示为‘ACTIVE’的会话。这些“幽灵会话”早已名存实亡,与客户端失去了联系,但它们既不响应常规的alter system kill session命令,也不受idle_time参数的限制。结果就是,它们持续占用着PGA内存、锁以及全局队列资源,在RAC这种共享架构下,极易引发全局缓存(GC)等待的连锁反应,拖累整个集群的性能。

Oracle RAC如何清理无效的数据库连接?调整SQLNET超时

问题的根源,往往不在于数据库层面没有检测能力,而在于SQL*Net网络层默认没有开启主动探测或超时清理机制。要知道,在默认配置下,TCP连接的保活(keepalive)是由操作系统控制的,比如Linux系统默认的2小时超时,这远远超出了绝大多数业务场景的容忍范围。

  • 如何检查当前无效会话? 可以运行以下查询,找出那些状态为ACTIVE但最后一次调用已超过5分钟的会话:
    SELECT sid, serial#, username, status, server, program, sql_id, last_call_et FROM v$session WHERE status = 'ACTIVE' AND last_call_et > 300 AND username IS NOT NULL;
  • 如何确认会话是否真的无响应? 对于可疑的会话ID,查询v$session_wait视图。如果发现其等待事件(event)是‘SQL*Net message from client’,并且状态(state)为‘WAITING’,但等待时间(seconds_in_wait)却在持续累加,这基本就能断定客户端已经失联了。
  • RAC环境下的特有风险: 这类幽灵会话在集群实例间进行状态同步或争用全局资源时,可能会被其他节点反复尝试处理,无形中放大了集群的内部通信开销,让问题雪上加霜。

sqlnet.ora里必须配的3个超时参数

单纯依赖数据库的resource_limitidle_time参数,对这类连接是无能为力的。必须在$ORACLE_HOME/network/admin/sqlnet.ora文件中显式启用SQL*Net层的探测机制。这里有三个关键参数,可以说是缺一不可,而且需要注意它们的生效范围:

  • SQLNET.EXPIRE_TIME = 10:这是核心。它指示服务器每隔10分钟向空闲的客户端连接发送一个探测包(一个空的数据包)。需要明确的是,这并非“10分钟后断开连接”,而只是发起一次探测。只有当客户端对这次探测毫无响应时,连接才会在后续被真正关闭。
  • TCP.CONNECT_TIMEOUT = 60:这个参数主要影响新连接的建立阶段,比如TNS ping或首次登录尝试。对于已经建立的连接,它不起作用。但将其设置为一个合理的值(如60秒),可以有效避免因网络问题导致的大量连接请求堆积,阻塞监听器进程。
  • TCP.VALIDNODE_CHECKING = YES 配合 TCP.INVITED_NODES = (your_app_subnet):这组参数虽然不直接控制超时,但通过限制允许连接的主机,可以从源头上防止恶意扫描建立虚假连接,间接减少了无效连接产生的可能性。

⚠️ 一个关键的大坑: 在RAC环境中,SQLNET.EXPIRE_TIME这个参数必须在所有节点上保持配置一致。否则,可能出现一个节点因探测失败断开了连接,而客户端重连时被分配到另一个节点,却可能错误地复用了旧的连接句柄,导致会话状态陷入混乱。修改完sqlnet.ora后,数据库实例无需重启,但必须重启监听器(lsnrctl)以使新配置生效。

ALTER SYSTEM KILL SESSION不生效?直接查SPID杀OS进程

有时候,你会发现v$session中的会话状态已经变成了‘KILLED’,但它占用的资源却迟迟没有释放。这在RAC环境中尤其常见,可能因为会话涉及跨实例的锁等待。此时,干等着PMON进程来清理可不是好主意,更主动的做法是定位到对应的操作系统进程并强制终止。

  • 第一步,查找操作系统进程ID(SPID):
    SELECT s.sid, s.serial#, s.status, p.spid, s.program FROM v$session s, v$process p WHERE s.paddr = p.addr AND s.sid = ;
  • 第二步,在会话所在的RAC节点上执行强制终止: 在Linux系统上使用 kill -9 ;在Windows系统上则使用 orakill
  • 第三步,验证清理结果: 执行 SELECT count(*) FROM v$process WHERE spid = '';,如果返回结果为0,就说明进程已被成功清除。

需要理解的是,ALTER SYSTEM KILL SESSION命令本身只是给会话打上一个“待清除”的标记,真正的清理工作是由后台进程PMON周期性地扫描来完成的(默认每3秒一次)。如果这个会话恰好持有未提交的DML锁,或者正卡在两阶段提交的中间状态,PMON的清理动作可能会被延迟数分钟甚至更久。在这种情况下,强制杀掉操作系统进程往往是唯一立竿见影的方法。当然,操作前最好通过v$transaction视图确认一下该会话是否还有未提交的事务,以评估强制终止的风险。

监听器日志里看真实断连时间点

数据库内部的视图只能告诉我们会话“何时被标记为失效”,如果想追踪网络层实际断开连接的确切时刻,就必须去查阅$ORACLE_HOME/network/log/listener.log这个监听器日志文件。

  • 搜索关键错误码: 重点关注TNS-12535(操作超时)、TNS-12608(发送超时)以及Failed to accept a connection这类信息。
  • 典型的日志记录如下:
    TNS-12535: TNS:operation timed out  TNS-12608: TNS:send timeout  ns secondary err code: 12535  nt main err code: 0
  • 结合时间戳和客户端IP地址进行分析, 可以反向推断出问题的源头:到底是应用程序侧的心跳机制缺失,还是中间的负载均衡设备(如F5、云负载均衡器)主动切断了连接。如果同一个IP地址频繁出现TNS-12535错误,那么很大概率是应用程序没有正确关闭连接,或者连接池的超时配置设置得过长。

真正棘手的是那些“隐形”的连接——它们既没有在监听器日志中留下错误记录,也没有被SQLNET.EXPIRE_TIME机制捕获。这类连接往往卡在操作系统的TCP FIN_WAIT2状态。排查它们需要从操作系统层面入手,例如使用netstat -an | grep :1521 | grep FIN_WAIT2这样的命令。遇到这种情况,调整的焦点通常就不再是数据库参数了,而是操作系统的内核网络参数,比如net.ipv4.tcp_fin_timeout

来源:https://www.php.cn/faq/2302693.html
上一篇如何处理SQL存储过程海量数据_分段处理与批量提交技巧 下一篇如何实现SQL存储过程只读访问_限制存储过程DML操作
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
phpMyAdmin批量导入多个小型SQL碎片文件方法
数据库 · 2026-07-05

phpMyAdmin批量导入多个小型SQL碎片文件方法

许多开发者习惯将多个小型SQL碎片文件一同上传到phpMyAdmin的导入页面,误以为平台能像文件夹一样批量处理——但实际情况是,系统仅识别第一个文件,其余文件会被静默忽略,无法执行。 根本原因其实并不复杂:phpMyAdmin的导入机制本质上是一个单文件上传接口。其import页面仅包含一个字段,

phpMyAdmin设置表AUTO_INCREMENT起始值的方法
数据库 · 2026-07-05

phpMyAdmin设置表AUTO_INCREMENT起始值的方法

phpMyAdmin里改AUTO_INCREMENT值,点“保存”却没反应? 其实,问题往往出在两个容易被忽视的细节上: 1 **错误点击了“保存”而非“执行”按钮**。phpMyAdmin 的“操作”页面中,AUTO_INCREMENT 输入框属于一个独立的表单。如果在字段旁点击“保存”

MySQL主从数据一致性检查pt-table-checksum使用方法和步骤详解
数据库 · 2026-07-05

MySQL主从数据一致性检查pt-table-checksum使用方法和步骤详解

pt-table-checksum 必须在主库执行——这一点,很多初次接触的人都会踩坑。它并不是“直连从库去比对”,而是借助 binlog 复制将校验逻辑同步过去,由从库本地重新计算,再写入 percona checksums 表。简单来说,你在主库发送一条类似 REPLACE INTO perco

MySQL连接被阻断错误原因及解除方法
数据库 · 2026-07-05

MySQL连接被阻断错误原因及解除方法

你是否遇到过 MySQL 报出 Host is blocked 的错误?先别急着怀疑密码是否正确——这本质上并非单纯的连接失败,而是你的 IP 地址已被 MySQL 主动列入黑名单。此时,即便输入完全正确的密码,数据库也会毫不留情地拒绝访问。要想立刻解除封锁,唯一的办法就是清空 host cache

MySQL 8.0跨库联合查询权限配置详解
数据库 · 2026-07-05

MySQL 8.0跨库联合查询权限配置详解

MySQL 8 0 的跨库联合查询功能原生内置,无需额外安装插件或修改配置文件。很多开发者遇到 SQL 语法正确却报 ERROR 1142 的情况时,常会困惑——其实并非 MySQL 限制跨库操作,而是权限验证环节未通过。 简而言之,跨库查询受阻的根源通常不是功能未启用,而是权限分配不完整或授权语句