在我的组织中,Oracle 数据库是 2 节点 RAC 数据库。集群的每个成员都有一个重新启动计划,即:
节点 1 - 每月第一个星期日凌晨 1:00 节点 2 - 每月第二个星期日凌晨 1:00
每当这些节点重新启动时,我都会在 J2EE 应用程序日志文件中看到以下异常:
org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.java:209)
... 154 more
Caused by: java.sql.SQLRecoverableException: ORA-01089: immediate shutdown in progress - no operations are permitted
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:389)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:382)
at oracle.jdbc.driver.T4C7Ocommoncall.processError(T4C7Ocommoncall.java:93)
at oracle.jdbc.driver.T4CTTIfun.receive
我们的 DBA 表示“我们在本地执行关闭事务。它应该尝试等待正在进行的事务完成并且不允许新事务。”
正如我上面提到的,在 2 个节点中,一次只有一个节点会重新启动,并且考虑到 DBA 的回答......我们的应用程序在重新启动过程中不应阻塞数据库。
我的问题是,为什么我的应用程序会抛出此异常?为什么我的应用程序尝试连接到正在关闭的数据库节点?
最佳答案
您的应用程序并未尝试连接到正在关闭的节点。关机开始时它已经连接。
我假设您的应用程序在中间层维护一个连接池。因此,据推测,就在其中一个节点重新启动之前,您的连接池已打开与两个节点的连接。当 DBA 执行关闭事务
时,具有 Activity 事务的 session 可以完成,但连接池中连接到正在关闭的节点的大多数 session 此时不会有 Activity 事务观点。当您从连接池获取这些连接之一并尝试启动事务时,您将收到此错误。
最有可能的是,您希望捕获此错误并重新连接,这将导致与剩余节点建立新连接。您收到的错误是 SQLRecoverableException
,因此尝试恢复通常是有意义的。
关于java - 在 J2EE 应用程序中优雅地处理 DB 节点重启,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31793882/