深入详解 Oracle  data change notification  

0、什么是 Oracle  data change notification  ?
当有多个应用程序或者进程操作同一个数据库时,其中进程1对Oracle中的某个表Table1进行插入、删除、修改等操作,进程2想在第一个进程操作完成后进行相应的操作。有没有什么方法让进程2获取到进程1的操作?
类似进程、多线程的同步机制,或者消息响应机制。在Oracle中也有类似的实现,该机制名称即为: data change notification。
       Database Change Notification的 作用 就是:当数据库中的数据发生变化的时候,自动发出一个通知。
1、支持Oracle版本
Oracle 10gR2 或者以上版本。
2、  data change notification支持的操作
(1)   数据库状态变化 Database status changes : startup and shutdown
(2)  数据库对象变化 Database objects changes :
1) DDL changes : alter or drop actions
2) DML changes : insert, delete, update actions

 用Database Change Notification有三个步骤:

     1)注册: 指定数据库要监听的查询。数据库可以监听DML(Data Manipulation Language)事件,DDL(Data Definition Language)事件,和global 事件(例如关闭数据库)。

  2)通知:一旦数据库中的数据发生变化,数据库将自动发出通知,我们要在我们的程序中定义事件处理操作。

  3)响应:在我们的程序中,一旦收到通知,我们一般情况下会自动更新data cache,当然我们可以通知用户数据发生改变,由他来决定是否进行更新。

3、两种使用方法
3.1 OTL data change notification源码详解
示例源码参考资料:
【1】http://otl.sourceforge.net/otl4_subscriber.htm

【2】http://otl.sourceforge.net/otl4_ex585.htm 
使用中在subs.subscribe()接口会出现Bug:
bug号及详情——ORA-24912: Listener thread failed. Listen failed.
Google提供的解决方案:The client needs to be restarted。(但测试不凑效)
错误及详见我的提问: http://bbs.csdn.net/topics/391054125
http://stackoverflow.com/questions/30847188/when-use-change-notification-interface-the-ora-24912-listener-thread-failed-l
截止2015-6-16,根本原因还没有找到,即该Demo未测试成功。
2015-6-23, 发现错误原因: 和代码中通过putenv()设置有关,不使用putenv(),改成直接将文件、库包含到工程中,该Bug便不存在。

3.2 ocilib data change notification源码详解
示例源码参考资料:
http://orclib.sourceforge.net/doc/html/group___ocilib_c_api_subscriptions.html
//代码解析(VS2010 C++实现,已经验证过)
#include "stdafx.h"
#include "ocilib.h"
#pragma comment (lib, "ociliba.lib")#ifdef _WINDOWS
#define sleep(x) Sleep(x*1000)
#endif
#define wait_for_events() sleep(5000)void event_handler(OCI_Event *event);
void error_handler(OCI_Error *err);int main(void)
{
OCI_Connection *con;
OCI_Subscription *sub;
OCI_Statement *st;printf("=> Initializing OCILIB in event mode...\n\n");//0.第二个参数为原有的oracle的DLL所在的路径名称。
if (!OCI_Initialize(error_handler, "oracle", OCI_ENV_EVENTS))
return EXIT_FAILURE;printf("=> Connecting to usr@db...\n\n");
//1.连接 第一个参数格式:【IP:端口/服务名】,第二个参数:登录用户名,第三个参数:密码。
con = OCI_ConnectionCreate("100.200.10.50:1521/ts", "tss", "psdts**", OCI_SESSION_DEFAULT);
OCI_SetAutoCommit(con, TRUE);printf("=> Creating statement...\n\n");
st = OCI_StatementCreate(con);printf("=> Creating tables...\n\n");
//2.创建数据表
OCI_ExecuteStmt(st, "create table table1(code number)");
OCI_ExecuteStmt(st, "create table table2(str varchar2(10))");printf("=> Registering subscription...\n\n");//3.注册通知事件 sub-00 为通知名称.
sub = OCI_SubscriptionRegister(con, "sub-00", OCI_CNT_ALL, event_handler, 5468, 0);
printf("=> Adding queries to be notified...\n\n");
OCI_Prepare(st, "select * from table1");
OCI_SubscriptionAddStatement(sub, st);
OCI_Prepare(st, "select * from table2");
OCI_SubscriptionAddStatement(sub, st);//等待响应注册事件
wait_for_events(); //可以Sleep足够时间一直等待,当有其他进程进行修改表的操作,该处就会有响应。// 以下为测试用,可以不用执行。
// #if 0
// //4.执行对应数据库alter操作
// printf("=> Executing some DDL operation...\n\n");
// OCI_ExecuteStmt(st, "alter table table1 add price number"); //alter事件
// //等待5s,等待打印输出.
// wait_for_events();
//
//
// //5.执行数据库的inser,update操作。
// printf("=> Executing some DML operation...\n\n");
// OCI_ExecuteStmt(st, "insert into table1 values(1, 10.5)");
// OCI_ExecuteStmt(st, "insert into table2 values('shoes')");
// OCI_ExecuteStmt(st, "update table1 set price = 13.5 where code = 1");
// OCI_ExecuteStmt(st, "delete from table2 ");
// wait_for_events();
//
// //6.执行drop数据库表操作。
// printf("=> Droping tables...\n\n");
// OCI_ExecuteStmt(st, "drop table table1");
// OCI_ExecuteStmt(st, "drop table table2");
// wait_for_events();
//
// printf("=> Disconnecting from DB...\n\n");
// OCI_ConnectionFree(con);
// printf("=> Stopping the remote database...\n\n");
// OCI_DatabaseShutdown("db", "sys", "sys",
// OCI_SESSION_SYSDBA,
// OCI_DB_SDM_FULL,
// OCI_DB_SDF_IMMEDIATE);
// #endifprintf("=> Unregistering subscription...\n\n");
OCI_SubscriptionUnregister(sub);
printf("=> Cleaning up OCILIB resources...\n\n");
OCI_Cleanup();
printf("=> Done...\n\n");return EXIT_SUCCESS;
}void error_handler(OCI_Error *err)
{
int err_type = OCI_ErrorGetType(err);
const char *err_msg = OCI_ErrorGetString(err);
printf("** %s - %s\n", err_type == OCI_ERR_WARNING ? "Warning" : "Error", err_msg);
}
void event_handler(OCI_Event *event)
{
unsigned int type = OCI_EventGetType(event);
unsigned int op = OCI_EventGetOperation(event);
OCI_Subscription *sub = OCI_EventGetSubscription(event);
printf("** Notification : %s\n\n", OCI_SubscriptionGetName(sub));
printf("...... Database : %s\n", OCI_EventGetDatabase(event));
switch (type)
{
case OCI_ENT_STARTUP:
printf("...... Event : Startup\n");
break;
case OCI_ENT_SHUTDOWN:
printf("...... Event : Shutdown\n");
break;
case OCI_ENT_SHUTDOWN_ANY:
printf("...... Event : Shutdown any\n");
break;
case OCI_ENT_DROP_DATABASE:
printf("...... Event : drop database\n");
break;
case OCI_ENT_DEREGISTER:
printf("...... Event : deregister\n");
break;
case OCI_ENT_OBJECT_CHANGED:printf("...... Event : object changed\n");
printf("........... Object : %s\n", OCI_EventGetObject(event));switch (op)
{
case OCI_ONT_INSERT:
printf("........... Action : insert\n");
break;
case OCI_ONT_UPDATE:
printf("........... Action : update\n");
break;
case OCI_ONT_DELETE:
printf("........... Action : delete\n");
break;
case OCI_ONT_ALTER:
printf("........... Action : alter\n");
break;
case OCI_ONT_DROP:
printf("........... Action : drop\n");
break;
}if (op < OCI_ONT_ALTER)
printf("........... Rowid : %s\n", OCI_EventGetRowid(event));break;
}printf("\n");
}
// data change notification效果截图
如下图的三个步骤:
注意:测试 空表insert一条记录的测试情况,需要 点下SQLDeveloper右面的“ 提交 ”按钮!
4、两种思路对比及Bug分析反思
周一下午临危受命,预期周一晚上完成data change notification的验证。
但是最终测试发现有RA-24912: Listener thread failed. Listen failed的Bug。
Google及Stackoverflow了N多资料,都没有解决方案。
一直持续到周二下午4点,在OTL尝试了N多方法都没有解决。
试验思路包括:
1)授权本地用户具有grant 权限,即能执行成功“grant change notifiation to 用户名”,已经授权,但Bug依然存在。
2)Stackoverflow老外提供思路,可能和服务有关,重启Oracle数据库,Bug依然存在。
3)从程序subscribe接口分析,但由于第三方接口,没有在深层打印日志,没有理清根本原因。
且subscirbe接口为void类型,无返回值,只能通过捕获异常,得到错误。且错误信息就只有监听失败。
综上,既然OTL这条路不通,为何不去尝试下其他思路。
当在Google输入"oracle data change notification C++" 关键词,便找到了3.2的实现。
反思:
1、对于不熟悉的领域,不能“一棵树上吊死”,当尝试N久一条路不通, 且业界大牛也没有好的方案的时候,可以考虑换换思路,说不定会柳暗花明。
2、当然,对于第一条路的Bug为什么存在,作为程序员还是要抽业余时间追根究底,最终解决掉。
2015-6-16 22:44 思于家中床前

作者:铭毅天下

转载请标明出处,原文地址:http://blog.csdn.net/laoyang360/article/details/46524519

如果感觉本文对您有帮助,请点击‘顶’支持一下,您的支持是我坚持写作最大的动力,谢谢!

深入详解Oracle data change notification相关推荐

  1. 详解Oracle架构、原理、进程,学会世间再无复杂架构

    详解Oracle架构.原理.进程,学会世间再无复杂架构 学习是一个循序渐进的过程,从面到点.从宏观到微观,逐步渗透,各个击破,对于Oracle, 怎么样从宏观上来理解呢?先来看一个图,这个图取自于教材 ...

  2. oracle中调试存储过程,详解Oracle调试存储过程

    详解Oracle调试存储过程 一 调试关键步骤 1.在要调试的存储过程右键,选择编辑以进行调试,截图如下: 2.点击小瓢虫,弹出调试窗口,截图如下: 3.输入7839员工编号,点击确认,进行调试,截图 ...

  3. 建oracle簇表,详解ORACLE簇表、堆表、IOT表、分区表

    详解ORACLE簇表.堆表.IOT表.分区表 簇和簇表 簇其实就是一组表,是一组共享相同数据块的多个表组成.将经常一起使用的表组合在一起成簇可以提高处理效率. 在一个簇中的表就叫做簇表.建立顺序是:簇 ...

  4. 视频教程-Oracle数据库从入门到实用教程详解-Oracle

    Oracle数据库从入门到实用教程详解 全栈工程师,2010年从事软件开发以及软件教育培训工作,至今将近十余年,在项目的开发,设计,到管理上积累了丰富的实战经验,教学风格上通俗易懂,问题解答环节一对一 ...

  5. Oracle一张表写多个触发器,详解oracle中通过触发器记录每个语句影响总行数

    详解oracle中通过触发器记录每个语句影响总行数 需求产生: 业务系统中,有一步"抽数"流程,就是把一些数据从其它服务器同步到本库的目标表.这个过程有可能 多人同时抽数,互相影响 ...

  6. oracle调试存储过程加断点,详解Oracle调试存储过程

    详解Oracle调试存储过程 一 调试关键步骤 1.在要调试的存储过程右键,选择编辑以进行调试,截图如下: 2.点击小瓢虫,弹出调试窗口,截图如下: 3.输入7839员工编号,点击确认,进行调试,截图 ...

  7. 详解Oracle AWR运行日志分析工具

    在Oracle数据库学习和使用中,遇到性能问题,首要的步骤就是导出AWR分析报告,AWR是Oracle的一个脚本工具,通过周期性快照记录下当时的所有运行数据,数据库管理员可以导出其中一部分数据进行分析 ...

  8. oracle scur,详解Oracle游标的简易用法

    下面看下Oracle游标的简易用法,具体代码如下所示: create or replace procedure NW_DelYW(iOPERATION_ID number, sUserID varch ...

  9. oracle 总转横函数,详解Oracle行列转换函数-pivot函数和unpivot函数-多智时代

    今天主要介绍一下Oracle行转列及列转行常见函数,下面一起来看看吧! 行列转换 pivot函数:行转列函数 语法:pivot(任一聚合函数 for 需专列的值所在列名 in (需转为列名的值)): ...

最新文章

  1. windows下mysql和linux下mysql主从配置
  2. 要让OKR真正”OK“,这三点一定要注意!
  3. MySQL 高级 - 存储过程 - 语法 - repeat循环
  4. Fedora中允许mysql远程访问的几种方式
  5. 关于ELMo,面试官们都怎么问
  6. 剑指 Offer 28. 对称的二叉树【无取巧,易于理解!】
  7. 使用.gitignore忽略编译自动生成的那些文件
  8. Linux-可重入函数(day10)
  9. 2022年上半年软件设计师下午真题及答案解析
  10. python乌龟吃鱼
  11. 如何在职场上获得良好的起点
  12. 【计算机视觉】简述对MSAA(多尺度注意力融合)的理解
  13. AUTOCAD——中心线绘制、CAD默认线宽是多少?可以修改吗?
  14. android工具类
  15. OJ每日一练——羞涩的答复
  16. mysql win10 msi下载_Windows10 MYSQL Installer 安装 (msi 安装)
  17. MySQL参数binlog-do-db对binlogs写入的影响
  18. 滤镜原理_中性密度滤镜的工作原理以及如何使用它们进行更好的摄影
  19. 新的开始 ,新的结束
  20. 英语四级作文计算机,英语四级作文范文:电脑

热门文章

  1. 读了这个小说,比较欣赏这个观点
  2. 计算苹果的价格(计算物品类的价格可借鉴)
  3. 【渲染引擎】agg介绍
  4. 下列选项中表示mysql逻辑非运算的有_MySQL逻辑运算符
  5. MySQL运算符(逻辑运算符,比较运算符,位运算符)
  6. 移宇科技全院血糖管理系统与闭环人工胰腺系统助力患者血糖管理
  7. Python 字典操作 总结
  8. 3GPP TS 29244-g30 中英文对照 | 7.2.1 General
  9. linux主机复制文件到同一网段其他设备
  10. 6-3 在数组中查找指定元素