2014-05-08 5 views
2

Bon temps!Délai de notification des modifications de données Oracle et flux de travail

Nous avons la fonction Oracle DCN configurée dans notre application Java. Tout fonctionne bien, mais il y a quelques problèmes sur l'arrêt de l'application. Si l'application est arrêtée de manière inattendue (par exemple, un processus Tomcat est arrêté via la commande kill -9), les abonnés DCN sont laissés pendu dans un DB (select * from user_change_notification_regs;). En outre, je peux voir que chaque abonné a un timeout 4294967295-second.

Alors quelqu'un pourrait, s'il vous plaît, suggérer:

1. comment configurer le délai d'attente pour un abonné;
2. Pourquoi les abonnés restent-ils pendus même après que toutes les connexions JDBC sont arrêtées? Eh bien, s'il n'y a pas de correspondance entre une connexion JDBC et un abonnement DCN, comment Oracle enverra-t-il DCN à une application java lorsque la dernière sera finalement lancée (y a-t-il des opérations ping d'Oracle vers une application? un abonnement durable dans JMS)?

MISE À JOUR: J'ai trouvé une réponse au premier point . Il y a le paramètre OracleConnection.NTF_TIMEOUT qui pourrait être réglé pour un 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); 

Répondre

0

Les enregistrements que vous avez persisté dans le tableau user_change_notification_regs doit être supprimé explicitement depuis SGBD ne garde pas trace de cette « La connexion JDBC qui a préparé cette connexion est encore en vie ' qui nécessite un mécanisme de battement de coeur. Par conséquent, lorsque votre serveur redémarre, vous devez explicitement supprimer (désenregistrer) ces enregistrements. Voici un exemple.

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); 
     } 

Vous pouvez simplement placer ce code dans un bloc statique d'une classe ou dans une méthode d'initialisation qui ne sera exécutée qu'une seule fois. Si vous définissez un délai d'attente pour l'écouteur, le pilote côté serveur Oracle active le mécanisme de rythme cardiaque pour votre connexion, ce qui peut légèrement diminuer les performances de l'application. Oracle finira par nettoyer les enregistrements morts.

0

Vous pouvez également activer keep alive dans le fichier de paramètres sqlnet sur le serveur pour accélérer ce processus de nettoyage.

Questions connexes