PL/SQL的EXCEPTION无法捕获连接中断,因为ORA-03114、ORA-03113等错误发生在SQL*Net网络层,语句未送达数据库或响应丢失,PL/SQL引擎已失上下文,不进入异常处理分支。
pl/sql 本身不支持自动重连,连接中断后必须由客户端(如 sql developer、pl/sql developer)或应用层主动重建会话;你写的 pl/sql 块一旦遭遇 ora-03114(未连接到 oracle)、ora-03113(通信通道中断)等错误,就已无法继续执行——异常根本不会进入 exception 块,因为那不是 pl/sql 运行时异常,而是网络/会话级断连。
为什么 PL/SQL 的 EXCEPTION 捕获不到连接中断?
Oracle 的 EXCEPTION 只能捕获在当前会话中成功发起并返回错误码的 PL/SQL 执行错误(比如 NO_DATA_FOUND、ZERO_DIVIDE)。而连接中断发生在 SQL*Net 层,语句甚至没发到数据库,或发出去后收不到响应,此时 PL/SQL 引擎已失去上下文,直接报错退出。常见表现是:ORA-03114: not connected to ORACLE 或 ORA-01041: host language program did not invoke oracle,这类错误不会触发 WHEN OTHERS。
真正有效的“重连”必须在客户端或应用层做
PL/SQL 是服务端语言,它不管理连接生命周期。所谓“重连”,实际要靠调用它的客户端工具或外部程序完成:
- SQL Developer:启用
Tools → Preferences → Database → Keep Alive,设置心跳间隔(如 60 秒),避免中间设备(防火墙/NAT)静默断开 - PL/SQL Developer:勾选
Tools → Preferences → Connection → Check connection,每次执行前自动验证连接有效性,失败则弹窗提示重连 - Java/.NET 应用:用连接池(如 HikariCP、ODP.NET)配置
connection-test-query=SELECT 1 FROM DUAL和validation-timeout,配合auto-reconnect=true(注意 Oracle 官方驱动默认不支持 true auto-reconnect,需手动捕获 SQLException 后重建 DataSource)
能在 PL/SQL 里做的有限补救:检测会话状态 + 提前防御
虽然不能重连,但可在关键操作前检查会话是否活跃,避免盲目执行导致后续逻辑混乱:
- 用
SELECT SYS_CONTEXT('USERENV', 'SESSIONID') FROM DUAL验证会话 ID 是否有效(若报ORA-03114,说明已断) - 对长事务或循环批量操作,每 N 次迭代后显式执行
SELECT 1 INTO v_dummy FROM DUAL,快速探活;捕获WHEN OTHERS THEN IF SQLCODE IN (-3113, -3114) THEN ... END IF;,然后RAISE_APPLICATION_ERROR(-20001, 'Session lost, aborting'); - 避免在 PL/SQL 中依赖长时间空闲连接——把大任务拆成小批次,每次提交后由客户端决定是否继续
最常被忽略的一点:你以为在 PL/SQL 里写个 WHEN OTHERS 就能兜住所有错误,但连接中断类错误根本进不了这个分支。真正的防线不在存储过程里,而在连接建立、保活、超时配置和客户端重试策略上。











