Database Change Notification

本文介绍了数据库变更通知(DatabaseChangeNotification)的作用、原理及实现步骤。通过注册、指定监听表和响应机制,实现对数据库变更的实时通知,适用于读多写少的应用场景。实例展示了在Linux环境下使用Oracle JDBCDriver进行配置与代码实现,解决了实际部署中监听不到数据改变的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Database Change Notification的作用就是当数据库中的被监听table变化时(包括数据和表结构的更改),自动向应用程序发出一个通知。这对读多写少应用的缓存更新,以及避免轮询数据库很有用。

需要3个步骤:
1. 注册。

2. 用一个查询表示监听哪个(些)表的修改通知。

3. 响应。

原理是程序另起了一个线程 并向数据库注册了一个IP和端口,当数据库数据发生改变时通知程序。



官方说支持11G,其实10.2也可以跑

运行环境:linux jdk6

jar :ojdbc6.jar


代码:

import java.lang.reflect.Field;
import java.net.InetAddress;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

import oracle.jdbc.OracleStatement;
import oracle.jdbc.dcn.DatabaseChangeEvent;
import oracle.jdbc.dcn.DatabaseChangeListener;
import oracle.jdbc.dcn.DatabaseChangeRegistration;
import oracle.jdbc.driver.OracleConnection;
import oracle.jdbc.pool.OracleDataSource;

public class Test {

 public static void main(String[] a) {
   try {
     OracleDataSource dataSource = new OracleDataSource();
     dataSource.setUser("***");
     dataSource.setPassword("***");
     dataSource.setURL("jdbc:oracle:thin:@192.168.***.***:1521:***");
     final OracleConnection conn = (OracleConnection) dataSource.getConnection();
     Properties prop = new Properties();
     prop.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS, "true"); // 要取得更改记录的rowid
     // prop.setProperty(OracleConnection.DCN_IGNORE_DELETEOP, "true");
     // // 忽略delete
     prop.setProperty(OracleConnection.NTF_TIMEOUT, "3600"); // 设置超时,这里是1个小时,届时数据库和驱动器的资源将自动释放。如果为0或不设置,则永不过期,直到程序停止监听,当数据库发送更新通知时,因没有监听端口,数据库随后释放资源。
     DatabaseChangeRegistration databaseChangeRegistration = conn.registerDatabaseChangeNotification(prop);
     OracleStatement statement = (OracleStatement) conn.createStatement();
     statement.setDatabaseChangeRegistration(databaseChangeRegistration);
     databaseChangeRegistration.addListener(new DatabaseChangeListener() { // 增加事件监听

         public void onDatabaseChangeNotification(DatabaseChangeEvent databaseChangeEvent) {
           System.out.println("DCNListener: got an event (" + this + ")");
         }
       });

     // add objects:

     statement.executeQuery("select * from t_12580_shop");
     statement.close();
     conn.close();
     System.out.println("Registered database change notification for table:t_12580_shop");

   }
   catch (Exception e) {
     System.out.print(e.getLocalizedMessage());
   }
 }
}


 


当你注册一个SELECT查询,你注册的是所涉及的表的名称,而不是查询本身。换句话说,你可能会选择一个表中的单一行,如果另一行被更新时,系统会通知您,虽然您的查询的结果并没有改变。

在放到线上环境时出现了程序监听不到数据改变的问题,查看源码后发现向数据库注册的IP是127.0.0.1

源码中获取本机IP的代码是InetAddress.getLocalHost().getHostAddress()

需要在/etc/hoses中配置hoseName 和内网IP的 映射,配置过后成功运行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值