【发布时间】:2020-06-17 23:42:59
【问题描述】:
我试图弄清楚为什么我们的 Oracle 11g 行为不端。我们在使用 JDBC 访问数据库的所有作业中都收到以下错误:
Error message: java.sql.SQLRecoverableException: IO Error: Connection reset
在任何人不高兴之前,是的,我已经检查了堆栈溢出的其他相关链接(天知道还有多少其他网站)。到目前为止没有任何帮助,我想知道接下来我可以尝试什么。
过去几个月情况恶化了,唯一改变的是访问数据库的作业在 docker 容器中运行。唯一受影响的数据库是 oracle 11g(我们还有其他几个数据库,包括 oracle 12c)。使用sqlplus访问11g的数据库没有问题。
由于这是一个连接的事情,我自然检查了文件tnsnames.ora 和listener.ora。这是它们包含的内容(有问题的数据库是 SID=TMF)。
tnsnames.ora:
GLOB =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = linuxoracle11)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = GLOB)
)
)
STATIC =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = linuxoracle11)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = STATIC)
)
)
TMF =
(DESCRIPTION =
(SDU=2048)
(TDU=2048)
(ADDRESS = (PROTOCOL = TCP)(HOST = linuxoracle11)(PORT = 1521))
(CONNECT_DATA =
(SERVER = SHARED)
(SERVICE_NAME = TMF)
)
)
DEMO =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = linuxoracle11)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = DEMO)
)
)
HONDADB =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = linuxoracle11)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = HONDADB)
)
)
TEMP =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = linuxoracle11)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = TEMP)
)
)
EXTPROC_CONNECTION_DATA =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
)
(CONNECT_DATA =
(SID = PLSExtProc)
(PRESENTATION = RO)
)
)
listener.ora:
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = TMF)
(ORACLE_HOME = /home/oracle/app/oracle/product/11.2.0/dbhome_1)
(SID_NAME = TMF)
)
(SID_DESC =
(GLOBAL_DBNAME = STATIC)
(ORACLE_HOME = /home/oracle/app/oracle/product/11.2.0/dbhome_1)
(SID_NAME = STATIC)
)
(SID_DESC =
(GLOBAL_DBNAME = DEMO)
(ORACLE_HOME = /home/oracle/app/oracle/product/11.2.0/dbhome_1)
(SID_NAME = DEMO)
)
)
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = linuxoracle11)(PORT = 1521))
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
)
)
在我的一生中,我看不出哪里出了问题。侦听器跟踪日志有大量这样的条目:
09-JUN-2020 18:25:21 * service_died * TMF * 12537
09-JUN-2020 18:25:22 * service_register * TMF * 0
09-JUN-2020 18:25:27 * service_died * TMF * 12537
09-JUN-2020 18:25:28 * service_register * TMF * 0
Tue Jun 09 18:25:33 2020
09-JUN-2020 18:25:33 * service_died * TMF * 12537
09-JUN-2020 18:25:34 * service_register * TMF * 0
09-JUN-2020 18:25:39 * service_died * TMF * 12537
09-JUN-2020 18:25:40 * service_register * TMF * 0
Tue Jun 09 18:25:45 2020
09-JUN-2020 18:25:45 * service_died * TMF * 12537
09-JUN-2020 18:25:46 * service_register * TMF * 0
09-JUN-2020 18:25:51 * service_died * TMF * 12537
09-JUN-2020 18:25:52 * service_register * TMF * 0
Tue Jun 09 18:25:57 2020
09-JUN-2020 18:25:57 * service_died * TMF * 12537
09-JUN-2020 18:25:58 * service_register * TMF * 0
09-JUN-2020 18:26:03 * service_died * TMF * 12537
09-JUN-2020 18:26:04 * service_register * TMF * 0
我最近尝试解决此问题的方法是对 oracle community post 中的信息稍作改动。服务器上的设置:
[root@linuxoracle11 trace]# mv /dev/random /dev/xrandom
[root@linuxoracle11 trace]# ln -s /dev/urandom /dev/random
[root@linuxoracle11 trace]# ls -l /dev/*ndom
lrwxrwxrwx 1 root root 12 Jun 9 19:26 /dev/random -> /dev/urandom
crw-rw-rw- 1 root root 1, 9 Jun 9 09:58 /dev/urandom
crw-rw-rw- 1 root root 1, 8 Jun 9 09:58 /dev/xrandom
但是,这并没有解决问题,针对数据库运行的作业仍在中止。
最令人恼火的方面是有时作业运行无误。如果有人能暗示我应该朝哪个方向看,我将不胜感激。
编辑: 根据要求,这里是 sqlnet.ora 文件的内容:
SQLNET.RECV_TIMEOUT=5
SQLNET.INBOUND_CONNECT_TIMEOUT=5
是的,这是安装数据库系统时默认生成的。
还有人认为这可能是由于“登录风暴”造成的。这是值得怀疑的,因为我们在数据库上的实际用户很少。主要是我写的关于在 docker 容器中运行的那些工作。我检查了 oracle doco 和一些信息(再次来自 Burleson 咨询页面)并尝试了以下操作:
SQL> select resource_name, current_utilization, limit_value
2 from v_$resource_limit
3 where resource_name in ('processes', 'sessions');
RESOURCE_NAME CURRENT_UTILIZATION LIMIT_VALU
------------------------------ ------------------- ----------
processes 25 200
sessions 30 322
所以我们说的是几十个连接,而不是几百个。
Edit2:为了完整起见,这里是堆栈跟踪的一部分:
****** Jun 12, 2020 9:20:32 PM IO Error: Connection reset ******
java.sql.SQLRecoverableException: IO Error: Connection reset
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:752)
at oracle.jdbc.driver.PhysicalConnection.connect(PhysicalConnection.java:666)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:566)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:247)
...
Caused by: java.net.SocketException: Connection reset
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:115)
at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
at oracle.net.ns.DataPacket.send(DataPacket.java:209)
at oracle.net.ns.NetOutputStream.flush(NetOutputStream.java:215)
at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:302)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:249)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:171)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:89)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:123)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:79)
at oracle.jdbc.driver.T4CMAREngineStream.unmarshalUB1(T4CMAREngineStream.java:429)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:397)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:437)
at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:954)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:639)
... 38 more
【问题讨论】:
-
当它起作用时,它需要多长时间 - 不到 5 秒?你能包括你的
sqlnet.ora文件工具它有sent_timeout和recv_timeout设置(大概是5)吗? -
我已将sqlnet.ora 的内容添加到帖子中。至于需要多长时间,好吧,我们正在谈论连接到数据库通常需要多长时间。我写的关于在不同时间创建 jdbc 连接的作业,用于读取数据、读取目录数据、更新表等。为什么它有时会起作用,有时会不起作用,这就是我需要弄清楚的。
-
它是否有效取决于 JDBC 调用是否与
service_died消息一致,大概(再次!)。比较日志应该可以说明这一点。通话时间越短,越有可能侥幸逃脱;我认为,持续超过 5 秒的操作总是会失败。至于 SQL*Plus,这是一个本地遗赠连接吗?它不依赖于 SQL*Net,因此不会受到影响?如果您通过服务名称连接,您是否看到问题 - 例如sqlplus usr/pwd@//linuxoracle11:1521/TMF? -
@Alex Poole:比较日志?哪个?这对我来说是个问题,因为 Oracle 在各种地方都隐藏了日志和警报。我通常需要进行复杂的“查找”才能有机会找到一个。您对 sqlplus 的猜测是正确的。它在服务器上运行,因此不受 sqlnet 问题的影响。
-
您已经拥有的监听器跟踪日志,带有
service_died消息和时间戳;以及您的应用程序日志显示 JDBC 错误及其时间戳(希望在此之前提供一些信息)。当您收到 JDBC 错误时,它是否与service_died一致?当您没有收到 JDBC 错误时,时间是否显示service_registered和service_died之间正在发生?我很确定是这样,检查日志只会确认确实如此。