我在 Windows 2012R2 服务器上运行 Oracle 11g。出于某种原因,我们有一些代码尝试重新启动侦听器然后执行连接。此代码已在许多不同的服务器上运行多年,但在一个特定的服务器上,侦听器无法重新启动。
以下是侦听器尝试重新启动时在 listener.log 文件中发现的错误:
Started with pid=5132
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROCipc)))
Error listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=thehostname)(PORT=1521)))
TNS-12542: TNS:address already in use
TNS-12560: TNS:protocol adapter error
TNS-00512: Address already in use
64-bit Windows Error: 48: Unknown error
No longer listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROCipc)))
我已经设法使用此命令重现该问题:
net stop OracleOraDb11g_home1TNSListener && net start OracleOraDb11g_home1TNSListener
如果我像这样修改命令行:
net stop OracleOraDb11g_home1TNSListener && sleep 30 && net start OracleOraDb11g_home1TNSListener
侦听器正确重新启动。
我想端口 1521 停止后释放的速度不够快,但我不知道如何修复它。
这里的信息是 listener.ora 文件的内容:
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = C:\somepath\database\product\11.2.0\dbhome_1)
(PROGRAM = extproc)
)
(SID_DESC =
(GLOBAL_DBNAME = somevalue)
(SID_NAME = somevalue)
)
)
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
)
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = thehostname)(PORT = 1521))
)
)
)
LOGGING_LISTENER=on
VALID_NODE_CHECKING_REGISTRATION_LISTENER=on
这是按设计工作™。
TCP 套接字生命周期由数据库进程外部的 TCP 堆栈异步管理,并且在状态之间转换时涉及各种延迟。完全可以想象,在一台快速机器上,监听器将在几毫秒内终止并重新启动,这比完全释放套接字要快。
由于您无法控制 TCP 堆栈逻辑,因此在我看来,您唯一的替代解决方案是在启动侦听器之前引入一点延迟(正如您已经做过的那样)。您可能不需要完整的 30 秒;尝试更小的值。