在日常的系统运维和应用开发中,我们经常会遇到一个令人头疼的问题:“套接字异常(SocketException)”,例如:
java.net.SocketException: Connection reset
java.sql.SQLRecoverableException: IO Error: Socket read timed out
这类异常通常被认为是网络问题、连接池配置问题,甚至是客户端代码问题。但你是否想过,这些问题的根源可能来自数据库本身?特别是当你使用的是 Oracle 数据库时,ORA-03137 这个内部错误,很可能是“罪魁祸首”。
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:210)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at oracle.net.ns.Packet.receive(Packet.java:312)
at oracle.net.ns.DataPacket.receive(DataPacket.java:106)
at oracle.jdbc.driver.T4CMAREngineNIO.receiveB1Packet(T4CMAREngineNIO.java:220)
at oracle.jdbc.driver.T4CMAREngineNIO.receive(T4CMAREngineNIO.java:190)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:124)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:535)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1168)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1293)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3594)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3638)
当你在 Oracle 的告警日志或跟踪文件中看到如下内容:
Errors in file e:\app\administrator\diag\rdbms\gqdb\gqdb\trace\gqdb_ora_28448.trc
ORA-03137: TTC 协议内部错误: [12333] [64] [0] [98] [] [] [] []
恭喜你,你已经找到了问题的核心原因!
ORA-03137: TTC protocol internal error
表示 Oracle 客户端与服务器之间的 TTC 协议在通信过程中发生了内部错误。
TTC(Transparent Transport Layer)是 Oracle 用于处理客户端与服务器之间 SQL 通信的协议层,负责:
当 TTC 协议出现内部错误时,Oracle 会中断当前的 SQL 执行,并可能直接关闭连接。
SocketException: Connection reset
或 Socket read timed out
等错误。Java 应用执行 SQL:
PreparedStatement ps = connection.prepareStatement("SELECT * FROM users WHERE status = ?");
ps.setInt(1, 1);
ResultSet rs = ps.executeQuery();
如果 Oracle 因 ORA-03137 异常断开连接,客户端就会收到:
java.net.SocketException: Connection reset
ORA-03137 通常与绑定变量窥探(Bind Peeking)有关。为了解决这个问题,可以禁用该功能:
ALTER SYSTEM SET "_optim_peek_user_binds"=FALSE;
⚠️ 注意:这是一个 Oracle 隐含参数,建议在测试环境中先行验证。
某些版本(如 Oracle 11.2.0.3 及以下)存在较多与 TTC 协议相关的 Bug。建议升级到:
在 Java、Python、Node.js 等客户端程序中,建议:
SocketException
使用连接池(如 HikariCP、Druid)可自动剔除异常连接,提升系统稳定性。
避免因数据库异常导致客户端长时间阻塞。
SQL>showparameter _optim_peek_user_binds
输出示例:
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
_optim_peek_user_binds boolean FALSE
问题 | 原因 | 解决方案 |
---|---|---|
套接字异常(SocketException) | Oracle 端异常中断连接 | 修复数据库端 ORA-03137 |
ORA-03137 | 与绑定变量窥探机制有关 | 禁用 _optim_peek_user_binds |
连接不稳定 | 数据库异常关闭连接 | 升级数据库、启用 ACS、优化客户端连接逻辑 |
SocketException
ORA-03137
_optim_peek_user_binds
SocketException 并不总是客户端的问题,它可能只是数据库异常的“信号”。当你遇到这类问题时,不妨从 Oracle 端入手,排查是否有 ORA-03137 等内部错误,往往能更快地定位问题根源。