当前位置: 首页 > news >正文

Oracle数据库常见问题实战:从连接错误到自动清理空闲会话

Oracle 数据库常见问题实战:从连接错误到自动清理空闲会话,ORA-17800/ORA-00020/ORA-12537报错不要慌

在 Oracle 数据库运维中,连接失败进程数超限是最常遇到的两类问题,比如 ORA-17800 连接错误、ORA-00020 进程数超出限制。本文将结合实际场景,从问题排查、紧急处理到长期优化,提供一套完整的解决方案,尤其针对 “如何安全自动清理空闲会话” 给出可直接复用的脚本与部署步骤,帮助运维人员高效解决问题。
在这里插入图片描述

一、场景引入:两类高频错误的典型表现

日常运维中,我们常会遇到以下两类影响业务的错误,需先明确错误本质再针对性解决:

1. 连接错误:ORA-17800: Got minus one from a read call

当应用或工具(如 SQL*Plus、BI 工具)连接数据库时,出现如下报错:

Unable to connect to the database!Error connecting to database: (using class oracle.jdbc.driver.OracleDriver)ORA-17800: Got minus one from a read call. (CONNECTION\_ID=SWaSTbAmQEejl8RVwmLRfA==)

错误本质:JDBC 驱动与数据库服务器的网络连接被异常中断,核心原因集中在 “监听问题”“网络拦截” 或 “连接参数错误”。

2. 进程数超限:ORA-00020: maximum number of processes (150) exceeded

当用户尝试连接数据库时,出现连接失败并提示:

ORA-00020: maximum number of processes (150) exceededSP2-0157: unable to CONNECT to ORACLE after 3 attempts, exiting SQL\*Plus

在这里插入图片描述

错误本质:数据库当前进程数已达到PROCESSES参数上限,无法创建新连接。通常因 “应用连接泄漏”“并发过高” 或 “参数设置过小” 导致。

二、问题排查:先确认数据库自身状态

无论遇到哪种错误,第一步需先在数据库服务器本地确认数据库是否正常运行 —— 若服务器端本身异常,后续排查将无意义。

前提:登录数据库服务器并切换环境

  1. 通过 SSH 或本地终端登录服务器,切换至oracle用户(需权限):
su - oracle  # 切换用户,环境变量可能自动加载
  1. 若环境变量未自动加载(如ORACLE_SID未定义),手动设置:
export ORACLE\_SID=ORCL  # 替换为你的实例名(如生产库可能是PROD)export ORACLE\_HOME=/u01/app/oracle/product/19.3.0/dbhome\_1  # 替换为你的ORACLE\_HOME路径export PATH=\$ORACLE\_HOME/bin:\$PATH  # 加入命令路径

1. 检查 Oracle 实例是否正常运行

实例是数据库的核心进程集合,需先确认其状态:

  1. 通过sqlplus以 sysdba 身份登录(最权威的本地连接方式):
sqlplus / as sysdba  # 无需密码,依赖操作系统认证
  • 若能进入SQL>提示符,说明实例至少已启动;

  • 若提示 “ORA-12560: TNS:protocol adapter error”,说明实例未启动。

  1. 查看实例详细状态:
SELECT instance\_name, status, database\_status FROM v\$instance;

正常输出(需同时满足):

INSTANCE\_NAME    STATUS    DATABASE\_STATUS\---------------- --------- -----------------ORCL             OPEN      ACTIVE
  • STATUS=OPEN:实例已打开,可正常提供服务;

  • STATUS=MOUNTED:仅挂载数据库,未打开(需执行ALTER DATABASE OPEN;);

  • STATUS=SHUTDOWN:实例已关闭(需执行STARTUP;启动)。

2. 检查监听器是否正常(解决 ORA-17800 关键)

监听器是数据库与外部的 “通信桥梁”,ORA-17800 常因监听异常导致:

  1. 查看监听器状态:
lsnrctl status  # 执行后查看输出

正常输出关键信息

Listening Endpoints Summary...  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=db-server-01)(PORT=1521)))  # 监听端口1521Services Summary...Service "ORCL" has 1 instance(s).  Instance "ORCL", status READY, has 1 handler(s) for this service...  # 服务已注册且READY
  • 若提示 “TNS-12541: TNS:no listener”:监听器未启动,需执行lsnrctl start启动;

  • 若监听器运行但无目标服务:需手动注册服务(执行ALTER SYSTEM REGISTER;)。

  1. 测试本地连接有效性(排除网络问题):
sqlplus scott/tiger@//localhost:1521/ORCL  # 替换为实际用户名、密码、服务名
  • 若本地能连接,远程不能:问题在 “防火墙” 或 “远程连接参数”;

  • 若本地也不能连接:问题在 “实例” 或 “监听器配置”。

三、紧急处理:ORA-00020 进程数超限的快速恢复

当出现 ORA-00020 错误时,需先释放进程资源,恢复业务连接能力,再做长期优化。

1. 优先:杀空闲会话释放进程(无需重启)

若还能以 sysdba 身份登录(sqlplus / as sysdba),通过杀 “长时间空闲的非关键会话” 释放进程:

\-- 步骤1:查看当前进程使用情况(确认是否真的满了)SELECT resource\_name, current\_utilization, max\_utilization, limit\_valueFROM v\$resource\_limitWHERE resource\_name IN ('processes', 'sessions');\-- 步骤2:查看所有非活动会话(按空闲时间排序,找可清理的目标)SELECT   sid, serial#, username, program, status,   last\_call\_et/60 AS idle\_minutes  # 空闲时间(分钟)FROM v\$sessionWHERE   username IS NOT NULL  # 排除空用户会话  AND username NOT IN ('SYS', 'SYSTEM')  # 排除系统用户(避免影响核心操作)  AND status = 'INACTIVE'  # 仅非活动会话ORDER BY last\_call\_et DESC;  # 按空闲时间倒序,优先杀最久的\-- 步骤3:杀指定空闲会话(替换sid和serial#为实际值)ALTER SYSTEM KILL SESSION '123,4567' IMMEDIATE;  # IMMEDIATE表示强制杀,无需等待

注意:杀会话前需确认usernameprogram(如 “报表工具”“测试用户” 的会话可优先清理,“核心应用” 会话需谨慎)。

2. 备选:重启数据库(万不得已时)

若已完全无法登录(所有进程被占用),只能通过重启释放所有进程:

\# 步骤1:以sysdba身份登录(若无法登录,用-prelim参数)sqlplus -prelim / as sysdba\# 步骤2:关闭并重启数据库SHUTDOWN IMMEDIATE;  # 正常关闭(等待事务完成,可能慢)\# 若关闭卡住,用强制关闭:SHUTDOWN ABORT;STARTUP;  # 启动数据库

风险提示SHUTDOWN ABORT会强制终止所有进程,可能导致数据不一致,仅在紧急时使用,且启动后需检查数据库完整性(如SELECT status FROM v$instance;确认OPEN)。

四、长期优化:从参数调整到自动清理

解决紧急问题后,需通过 “参数优化” 和 “自动化工具” 预防 ORA-00020 再次发生,核心是 “合理设置进程数” 和 “自动清理空闲会话”。

1. 调整 PROCESSES 参数(避免频繁超限)

PROCESSES参数定义数据库最大进程数,需根据业务并发量合理设置:

\-- 步骤1:查看当前参数值SHOW PARAMETER processes;\-- 步骤2:计算合理新值(建议为当前最大使用值的1.5\~2倍)\-- 例:当前最大使用120,设置为300(预留足够冗余)ALTER SYSTEM SET processes=300 SCOPE=spfile;  # SCOPE=spfile表示重启生效ALTER SYSTEM SET sessions=330 SCOPE=spfile;  # sessions通常为processes\*1.1+5(关联参数)\-- 步骤3:重启数据库使参数生效SHUTDOWN IMMEDIATE;STARTUP;\-- 步骤4:验证新参数是否生效SHOW PARAMETER processes;

经验值:生产库建议processes设置为 500~1000(根据服务器配置和并发量调整,避免过大浪费资源)。

2. 关键:安全自动清理空闲会话(核心脚本)

手动杀会话无法长期维持,需通过 “定时任务 + 安全脚本” 自动清理 “长时间空闲会话”,且需避免误杀关键业务会话。

2.1 安全版清理脚本(1 小时空闲阈值,避免误杀)

脚本特点:

  • 空闲阈值设为 1 小时(可调整),避免误杀短时间空闲的正常会话;

  • 排除SYS/SYSTEM系统用户,避免影响核心操作;

  • 过滤 LOB 操作相关会话,防止中断大文件处理;

  • 输出清理日志,方便审计。

创建脚本文件kill_idle_sessions.sql(可放在/home/oracle/scripts/目录):

SET SERVEROUTPUT ONDECLARE    v\_idle\_threshold  NUMBER := 60;  -- 空闲阈值:60分钟(1小时),可按需调整    v\_clean\_count     NUMBER := 0;   -- 统计清理的会话数BEGIN    DBMS\_OUTPUT.PUT\_LINE('================ 空闲会话清理开始 ================');    DBMS\_OUTPUT.PUT\_LINE('清理阈值:超过 ' || v\_idle\_threshold || ' 分钟的非活动会话');    DBMS\_OUTPUT.PUT\_LINE('清理时间:' || TO\_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));    DBMS\_OUTPUT.PUT\_LINE('------------------------------------------------');    -- 遍历符合条件的空闲会话    FOR rec IN (        SELECT             sid, serial#, username, program,            ROUND(last\_call\_et/60, 2) AS idle\_minutes        FROM v\$session        WHERE             username IS NOT NULL  -- 排除无用户名的会话            AND username NOT IN ('SYS', 'SYSTEM')  -- 排除系统用户            AND status = 'INACTIVE'  -- 仅非活动会话            AND last\_call\_et >= v\_idle\_threshold \* 60  -- 空闲时间超过阈值            AND NVL(sql\_id, 'x') NOT LIKE '%LOB%'  -- 排除LOB操作会话        ORDER BY last\_call\_et DESC    )    LOOP        -- 输出清理信息(用于审计)        DBMS\_OUTPUT.PUT\_LINE(            '清理会话:SID=' || rec.sid ||             ', SERIAL=' || rec.serial# ||             ', 用户=' || rec.username ||             ', 程序=' || rec.program ||             ', 空闲时间=' || rec.idle\_minutes || '分钟'        );        -- 执行杀会话操作        EXECUTE IMMEDIATE 'ALTER SYSTEM KILL SESSION ''' || rec.sid || ',' || rec.serial# || ''' IMMEDIATE';        v\_clean\_count := v\_clean\_count + 1;    END LOOP;    DBMS\_OUTPUT.PUT\_LINE('------------------------------------------------');    DBMS\_OUTPUT.PUT\_LINE('清理完成:共清理 ' || v\_clean\_count || ' 个空闲会话');    DBMS\_OUTPUT.PUT\_LINE('================ 空闲会话清理结束 ================');END;/
2.2 手动测试脚本(安全第一,先验证再定时)

在部署定时任务前,务必手动执行脚本,确认无误杀风险:

\# 步骤1:登录sqlplussqlplus / as sysdba\# 步骤2:执行脚本(替换为实际路径)@/home/oracle/scripts/kill\_idle\_sessions.sql

观察输出:确认清理的会话均为 “非核心业务”“长时间空闲” 的会话,无关键应用会话被误杀。

2.3 部署定时任务(Oracle DBMS_SCHEDULER)

通过 Oracle 自带的DBMS_SCHEDULER创建定时任务,实现 “每 2 小时自动清理”(可按需调整频率):

步骤 1:创建存储过程(封装清理逻辑)
CREATE OR REPLACE PROCEDURE P\_KILL\_IDLE\_SESSIONSAS    v\_idle\_threshold  NUMBER := 60;  -- 1小时空闲阈值    v\_clean\_count     NUMBER := 0;BEGIN    FOR rec IN (        SELECT sid, serial#        FROM v\$session        WHERE             username IS NOT NULL            AND username NOT IN ('SYS', 'SYSTEM')            AND status = 'INACTIVE'            AND last\_call\_et >= v\_idle\_threshold \* 60            AND NVL(sql\_id, 'x') NOT LIKE '%LOB%'    )    LOOP        EXECUTE IMMEDIATE 'ALTER SYSTEM KILL SESSION ''' || rec.sid || ',' || rec.serial# || ''' IMMEDIATE';        v\_clean\_count := v\_clean\_count + 1;    END LOOP;    -- (可选)记录清理日志到表(见下文“进阶:日志审计”)    INSERT INTO T\_IDLE\_SESSION\_CLEAN\_LOG (clean\_time, clean\_count)    VALUES (SYSDATE, v\_clean\_count);    COMMIT;END P\_KILL\_IDLE\_SESSIONS;/
  • 执行SELECT object_name, status FROM user_procedures WHERE object_name='P_KILL_IDLE_SESSIONS';,确认存储过程状态为VALID
步骤 2:创建定时任务(每 2 小时执行一次)
BEGIN    DBMS\_SCHEDULER.CREATE\_JOB (        job\_name        => 'JOB\_KILL\_IDLE\_SESSIONS',  -- 任务名(大写)        job\_type        => 'STORED\_PROCEDURE',        -- 任务类型:存储过程        job\_action      => 'P\_KILL\_IDLE\_SESSIONS',    -- 调用的存储过程        start\_date      => SYSTIMESTAMP,              -- 开始时间:立即开始        repeat\_interval => 'FREQ=HOURLY; INTERVAL=2', -- 执行频率:每2小时        end\_date        => NULL,                      -- 无结束时间(长期运行)        enabled         => TRUE,                      -- 创建后立即启用        comments        => '每2小时清理超过1小时的非核心空闲会话'    );END;/
步骤 3:验证定时任务状态
SELECT     job\_name, status, next\_run\_date,     repeat\_interval, commentsFROM user\_scheduler\_jobsWHERE job\_name = 'JOB\_KILL\_IDLE\_SESSIONS';
  • status=ENABLED,说明任务已启用;

  • 若需修改频率(如改为每 1 小时):

BEGIN    DBMS\_SCHEDULER.SET\_ATTRIBUTE (        name        => 'JOB\_KILL\_IDLE\_SESSIONS',        attribute   => 'repeat\_interval',        value       => 'FREQ=HOURLY; INTERVAL=1'    );END;/
2.4 进阶:日志审计(可选,增强可追溯性)

为了便于问题排查,建议创建 “清理日志表”,记录每次清理的时间和数量:

\-- 步骤1:创建日志表CREATE TABLE T\_IDLE\_SESSION\_CLEAN\_LOG (    log\_id        NUMBER PRIMARY KEY,    clean\_time    DATE NOT NULL,  -- 清理时间    clean\_count   NUMBER NOT NULL, -- 清理会话数    create\_time   DATE DEFAULT SYSDATE);\-- 步骤2:创建序列(用于日志ID自增)CREATE SEQUENCE SEQ\_CLEAN\_LOG\_IDSTART WITH 1INCREMENT BY 1NOCACHE NOCYCLE;\-- 步骤3:修改存储过程,插入日志(见上文存储过程中“可选”部分)\-- 注:需将INSERT语句中的T\_IDLE\_SESSION\_CLEAN\_LOG表名与实际一致,且添加log\_id:INSERT INTO T\_IDLE\_SESSION\_CLEAN\_LOG (log\_id, clean\_time, clean\_count)VALUES (SEQ\_CLEAN\_LOG\_ID.NEXTVAL, SYSDATE, v\_clean\_count);

后续可通过日志表查看清理历史:

SELECT \* FROM T\_IDLE\_SESSION\_CLEAN\_LOG ORDER BY clean\_time DESC;

五、常见问题 Q&A(避坑指南)

  1. Q:执行 ALTER SYSTEM KILL SESSION 后,会话状态仍为 KILLED,无法释放进程?

    A:KILLED 状态的会话需等待 “客户端断开连接” 才会释放进程,可强制清理操作系统进程:

\-- 步骤1:查询会话对应的操作系统PIDSELECT s.sid, p.spid FROM v\$session s, v\$process p WHERE s.paddr = p.addr AND s.status = 'KILLED';\-- 步骤2:在服务器端执行kill命令(替换SPID为实际值)kill -9 12345  -- 12345为上一步查询到的SPID
  1. Q:定时任务 JOB_KILL_IDLE_SESSIONS 没执行,是什么原因?

    A:检查两点:

  • 任务是否启用:SELECT status FROM user_scheduler_jobs WHERE job_name='JOB_KILL_IDLE_SESSIONS';(需为 ENABLED);

  • 数据库是否启用了 JOB 队列:SHOW PARAMETER job_queue_processes;(需大于 0,若为 0 则执行ALTER SYSTEM SET job_queue_processes=10 SCOPE=both;)。

  1. Q:如何避免误杀 “长连接应用” 的会话(如中间件连接池)?

    A:修改脚本中的过滤条件,排除特定程序的会话:

\-- 在WHERE子句中添加:排除中间件连接池(如WebLogic、Tomcat)AND program NOT LIKE '%weblogic%' AND program NOT LIKE '%tomcat%'

六、总结

本文从 “问题排查” 到 “紧急恢复”,再到 “长期自动化优化”,覆盖了 Oracle 数据库连接错误(ORA-17800)和进程数超限(ORA-00020)的完整解决方案:

  1. 连接错误:先查 “实例状态” 和 “监听器”,再分 “本地 / 远程” 定位网络问题;

  2. 进程超限:紧急时杀空闲会话,长期靠 “调参数 + 自动清理脚本”;

  3. 自动化脚本:核心是 “安全过滤条件”(排除系统用户、合理阈值)和 “定时任务部署”,兼顾效率与安全性。

建议运维人员根据实际业务场景调整参数(如空闲阈值、执行频率),并定期查看清理日志,确保方案稳定运行。

http://www.dtcms.com/a/454471.html

相关文章:

  • 网站开发项目管理步骤如何做国外的网站
  • 建设银行潍坊支行网站wordpress博客二次元
  • html5网站开发特点wordpress导出导入
  • 个人博客网站总结全网营销解决方案
  • 域名注册好后怎么建设网站官网浏览器
  • Smac Planner与 NavFn Planner 的对比分析
  • 傅里叶变换·思考
  • 南部县网站建设怎样建单位的网站
  • 虹桥做网站WordPress的主题制作教程
  • 太仓高端网站制作甘肃省建设银行校园招聘网站
  • 人力资源网站建设方案安装wordpress中文包
  • 江苏省建设厅网站建造师强制注销有哪些网站的搜索引擎
  • wordpress 多语言网站网站配图尺寸
  • 站长工具在线免费观看网络营销推广网站
  • tdk标签影响网站权重广州现在算什么风险地区
  • AssemblyScript 入门教程(9):直接内存管理
  • 新的南宁网站建设公司WordPress中文空格
  • 手机网站设计小程序wordpress用什么系统
  • STIP开源股票技术指标回测分析平台产品深度分析
  • 什么网站可以接室内设计做建设人力资源网
  • 图文详解Transformer模型——解码器输入(shifted input)详解
  • 网站推广方案策划书2000杭州g20网站建设公司
  • 网站导航栏图标js 访问wordpress
  • 品牌宣传网站建设网站开发软件和工具ide和编辑器
  • 自创网站怎么赚钱自己制作网站该怎么做
  • 怎么做网站导航栏哈尔滨网站建设报价价格
  • 没有显卡,浏览器如何免费调用本地大模型智能体
  • 阿里云电影网站建设教程丹阳网站建设机构
  • 关于Verilog和FPGA的自学笔记1
  • 网站怎么做ipfs郴州 网站建设