美好时光!
我们在Java应用程序中配置了Oracle DCN功能。一切正常,但应用程序关闭有一些麻烦。如果应用程序意外关闭(例如,通过kill -9
命令终止了tomcat进程),则DCN订阅者将被挂在数据库(select * from user_change_notification_regs;
)中。此外,我可以看到每个订阅者都有4294967295-second
超时。
有人可以,建议:
1。如何设置订阅者的超时;
2。即使在所有JDBC连接断开后,订阅者仍被绞死。好吧,如果JDBC连接和DCN订阅之间没有对应关系,那么当最后一个应用程序最终启动时,oracle如何将DCN发送到java应用程序(是否有从Oracle到应用程序的ping操作,或者类似于在JMS中持久订阅)?
更新:
我找到了第一个点的答案。可以为OracleConnection.NTF_TIMEOUT
设置DatabaseChangeRegistration
参数:
Properties properties = new Properties();
properties.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS, "true");
properties.setProperty(OracleConnection.DCN_BEST_EFFORT, "true");
properties.setProperty(OracleConnection.NTF_TIMEOUT, "3600");
DatabaseChangeRegistration databaseChangeRegistration = oracleConnection.registerDatabaseChangeNotification(properties);
答案 0 :(得分:0)
您必须明确删除user_change_notification_regs
表中持久存储的记录,因为DBMS无法跟踪'准备此连接的JDBC连接仍处于活动状态',这需要一个心跳机制。因此,当服务器重新启动时,您必须显式删除(取消注册)这些记录。这是一个例子。
try (Connection conn = ConnManager.getConnection();) {
if (conn.isWrapperFor(OracleConnection.class)) {
try (OracleConnection oracleConnection = conn.unwrap(OracleConnection.class);
Statement stmt = oracleConnection.createStatement()) {
ResultSet rs = stmt.executeQuery("select regid,callback from USER_CHANGE_NOTIFICATION_REGS");
while (rs.next()) {
long regid = rs.getLong(1);
String callback = rs.getString(2);
((OracleConnection) stmt.getConnection()).unregisterDatabaseChangeNotification(regid, callback);
}
}
}
} catch (SQLException ex) {
Logger.getLogger(TableBase.class.getName()).log(Level.SEVERE, null, ex);
}
您可以简单地将此代码放在类的静态块或初始化方法中,该方法只执行一次。如果为侦听器设置超时,oracle服务器端驱动程序会为您的连接启用心跳机制,这可能会略微降低应用程序性能。
答案 1 :(得分:0)