由于我们公司一个数据库两个应用在使用,导致一个应用修改了数据库,另一个应用用的缓存而不知道有更新还是原来的结果。原来的处理方式是采用session缓存的方式,用户登出了就清空缓存,这样只需要重新登录一次就得到最新的快照放在缓存中了,但现在新的要求是不登出就要实时刷新改了的内容。其实这种方式最好的处理办法是一个应用改了数据库通知另一个应用去刷新缓存,但是线下应用用vb写的成熟的产品,都是一帮老员工很难让他们去改点东西来适合新应用,都是新应用去套他们的。领导本来说直接不用缓存了,每次去读数据库,我觉得这样解决问题太粗暴了,之前的努力都白费了,就想通过一种查询数据库表是否改变了的方式进行折中处理,在应用里记录一个版本号或者最后修改时间,每次先去数据库读一次看看有没有变化,如果有变化就刷新缓存,如果没有变化就用缓存里的。

  我最先想到的是触发器,的确是可以这样实现,但最好不要这样做,因为数据库是另一个项目主要在用,我们不能去过多的改变数据库。我们项目支持的是oracle数据库,user_objects表里有个LAST_DDL_TIME字段,但这个不是我想要的,我想要表DML操作的记录。9i以上可以在user_tab_modifications视图里查找到想要的信息,user_tab_modifications收集自采集信息以来被改变表的dml操作量数据,一个表只有数据量被改变10%以上才会被定期采集信息,也可以执行过程

DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO进行实时采集。

  These views are populated only for tables with the MONITORING attribute. They are intended for statistics collection over a long period of time. For performance reasons, the Oracle Database does not populate these views immediately when the actual modifications occur. Run the FLUSH_DATABASE_MONITORING_INFO procedure in the DBMS_STATS PL/SQL package to populate these views with the latest information. The ANALYZE_ANY system privilege is required to run this procedure.

  所以用这种方式是不行的,为了时实还得不断地去执行exec dbms_stats.FLUSH_DATABASE_MONITORING_INFO这个命令,这种方式对数据库操作太多了。

于是有了下面这种方式:ora_rowscn

  oracle 10G开始提供的一个伪列ORA_ROWSCN,它又分为两种模式一种是基于block这是默认的模式(块级跟踪);还有一种是基于row上,这种模式只能在建里表时指定ROWDEPENDENCIES(行级跟踪),不可以通过后期的alter  table语句来将表修改为ROWDEPENDENCIES。我只需要判断这个表有没有被DML语句操作所以只需要用第一种模式就可以了,不需要精确到row上,所以简单用第一种就可以了。

  我们知道,每个Block在头部是记录了该block最近事务的SCN(SystemChangeNumber)的,所以默认情况下,只需要从block头部直接获取这个值就可以了,不需要其他任何的开销,Oracle就能做到这一点。但是这明显是不精确的,一个block中会有很多行记录,每次事务不可能影响到整个block中所有的行,所以这是一个非常不精准的估算值,同一个block的所有记录的ORA_ROWSCN都会是相同的,基本上没有多大的使用价值。

  如果在建表的时候开启行级跟踪选项,Oracle则可以为每一行记录精确的SCN,那么显然不能再直接从block头部获取。要获得足够的信息,肯定要付出一定的代价,Oracle必须为每一行存储这个实际的SCN。所以这个行级跟踪的选项,只能在建表的时候指定,而不能通过alter table来修改现有的表,否则需要修改每一行记录的物理存储格式,代价是可想而知的。

  在10g之前,很多系统要实现增量数据抽取,要么通过解析日志,要么加触发器,要么就在表上加一个时间截字段。ORA_ROWSCN其实就是第三种方式,只是这个字段由Oracle来维护,这样可以避免一些应用绕过时间截去更新其他字段带来的问题。

第一种方式(块级跟踪):

select ora_rowscn,
       dbms_rowid.ROWID_BLOCK_NUMBER(rowid) blockid,
       scn_to_timestamp(ora_rowscn)
  from hs_futures.fuentrust t
 order by scn_to_timestamp(ora_rowscn);

dbms_rowid.ROWID_BLOCK_NUMBER(rowid):是为获取数据所在块的ID

scn_to_timestamp(ora_rowscn):获取数据最所修改的时间

数据发现变化后通过上面SQL语句可以查看到数据最后修改的时间,注意因为是同一个块上,所以这个块上只要有DML操作那么所有数据的scn都更新了,所以凡是跟这条记录在同一个块上数据获取到的ora_rowscn和scn_to_timestamp(ora_rowscn)两个值都发生了相应的变化。

第二种方式(行级跟踪):

create table hs_futures.fuentrust_test1 rowdependencies  as
  select * from hs_futures.fuentrust

用以上语句创建一个基于ROWDEPENDENCIES模式的表,然后用第一种方法中的SQL去查询此表数据中的ora_rowscn,scn_to_timestamp(ora_rowscn)两个值,修改其中的某一条记录然后再去查询那个值发现发生变化的只是被修改那条记录的这两个值发生了变化,而在同一个块中没有被修改的其它记录这两个值是不会产生变化的。

注意DDL操作:只要现有表记录中的数据有发生变化那么SCN肯定就会发生更新,如删除有数据的列,但是如果索引删除/修改/增加及增加/者删除没有任何数据的列那么SCN是不会有任何变化。

  

--------------------------------------------------------------

由于我们的用户还有在用9i的数据库,所以放弃了上面的办法,还是采用加触发器的办法。

一开始我想将改变记录写在一个表里,但找了一下项目里没有一个恰当的表来记录这种数据,又不想随便加到一个表里,不就是一个计数器嘛,就想用序列来进行记录。

于是触发器这样写

CREATE OR REPLACE TRIGGER RECORD_DEPT_SCN
AFTER INSERT OR UPDATE OR DELETE ON DEPARTMENT
DECLARE temp NUMBER;
BEGIN
SELECT DEPT_SCN.NEXTVAL INTO temp FROM DUAL;
END;

在触发器里实现序列的自增,在oracle里我没有找到直接增加序列的方法,只能用这种曲线救国的方式了。(另外有一种直接去改序列底层对应的表sys.seq$的HIGHWATER字段,但这样太有侵入性了,还是算了)

序列这样写

DECLARE exist number;
BEGIN
SELECT COUNT(1) INTO exist FROM USER_SEQUENCES WHERE SEQUENCE_NAME='DEPT_SCN';
IF exist = 0 THEN
EXECUTE IMMEDIATE
'CREATE SEQUENCE DEPT_SCN
INCREMENT BY 1
START WITH 1
MAXVALUE 999999999
NOCACHE';
END IF;
END;

先判断有这个序列没,如果没有才创建。因为我们的sql在每一次项目启动的时候都会执行,所以必须做判断是否存在。

  这里我还学到一个新知识点,就是序列的CACHE,一般默认情况下是20,这个缓存的意义是多个connection来操作这个序列的时候,为了让性能更高,尽量少出现并发争夺,而采用的一种策略,比如cache是20,当前值是0,一个connection来了就把1到20的值全给这个connection用,connection在这个范围内自增序列不用再去访问序列本身了,以此类推另一个connection来了就把21到40给他用,所以这样就效率会提高,序列也会保证递增和唯一,但是不能保证连续,我这个应用想保持连续,而且使用频率是很少的,所以不担心什么性能问题,就不用CACHE了。

  另外说一个问题,就是你想调用序列的currval,必须先调用nextval,否则会报ORA-08002: 序列 SEQ1.CURRVAL 尚未在此会话中定义的错误,我想原因就是这个connection没去调用nextval,就是没分配给他一个缓存断,所以必须先调用。那么我想看当前值还得先自增一次,显然不科学,在 USER_SEQUENCES视图里的LAST_NUMBER就是这个系列的nextval的值,但通过SELECT LAST_NUMBER - 1 FROM USER_SEQUENCES WHERE SEQUENCE_NAME = 'DEPT_SCN' 获取的序列当期值可以不让序列自增一次,但是如果你用了CACHA这里获取的LAST_NUMBER其实是给出去缓存数之后下一次再给出缓存数开始的值,比如CACHA是20,你调用了一个nextval,那么去看这个值已经是21了。所以NOCACHE才能保证这里LAST_NUMBER - 1显示的是当前值。

  最难的问题解决了,剩下就是在项目里使用了,这个没什么难度就不说了,完成。

转载于:https://www.cnblogs.com/onlywujun/p/3755052.html

查看Orcale数据里的表是否有变化相关推荐

  1. vbs创建mysql数据库_vbs生成ACCESS数据里所有表的字段

    vbs生成ACCESS数据里所有表的字段 更新时间:2008年06月25日 08:38:32   作者: 生成ACCESS数据库里所有表及所有字段并生成一定格式的字符组合 databasename = ...

  2. 泛微OA ecology 配置了外部数据源,但是读取不到数据里的表?

    配置的数据源不仅需要有查询表数据的权限, 也需要读取系统表结构的权限. oracle数据库:系统表 相关表 user_tab_columns ,user_tables,user_views : sql ...

  3. 大数据里细看苏州旅游新变化

    刚刚过去的"十一"黄金周,苏州各地.各旅游景区推出了70多项特色鲜明的旅游节庆活动,吸引游客纷至沓来.据统计,7天时间苏州共接待境内外游客677.3万人次,同比增长8.34%,实现 ...

  4. 怎么查看atcoder的数据_多表数据联动查看,怎么做?

    最近表姐有些繁忙,这一切的繁忙源于一个复杂的任务,那就是老板安排我核对会员用户购物详情,也就是要对照"会员信息表"核对在线订单商品,数据虽然不多,但是需要一条条的搜索,然后来回切换 ...

  5. php 清除数据表中所有数据库,清除一个数据库里所有表的数据

    如果需要清除一个数据库里所有表的数据,则可用下面命令: exec sp_MSforeachtable TRUNCATE TABLE ? ******************************** ...

  6. 【ClickHouse】查看数据库容量和表大小的方法(system.parts各种操作方法)

    文章目录 1.概述 本文为博主九师兄(QQ:541711153 欢迎来探讨技术)原创文章,未经允许博主不允许转载. 1.概述 转载:[ClickHouse]查看数据库容量和表大小的方法(system. ...

  7. oracle删除库里的所有表,清空mysql指定库里全部表数据-自动删除所有表,有外键约束的表优先删除...

    清空mysql指定库里所有表数据-自动删除所有表,有外键约束的表优先删除 由于要清空数据库数据 ,手动非常麻烦.网上找了一下,有一个Oracle的,参照它,在其上修改一下用于Mysql,把代码奉献如下 ...

  8. 17.2.3 通过查看triggers数据表中的数据查看触发器的信息

    17.2.3 通过查看triggers数据表中的数据查看触发器的信息 在MySQL中,会将触发器的信息存储到information_schema数据库中的triggers数据表中.可以通过查看info ...

  9. 查看mysql数据表结构的两种方法你会吗?

    教你如何查看数据表结构 当我们创建完表之后,如何查看表结构,以便于确认该表符合我们的预期呢,我们可以使用describe或者show create table命令来查看mysql数据表结构,下面我们就 ...

最新文章

  1. 大话设计模式(十三 有了门面,程序员的程序会更加体面!)
  2. pythonmysql查询转list_python 数据库查询结果转对象
  3. Webpack实战(三):作为前端你不得不懂的Webpack资源入口和出口的配置
  4. c语言课程设计实验设备,C语言课程设计课程设计_力学实验设备管理系统
  5. ASP.NET AJAX,WCF,ADO.NET Entity 开发实例
  6. 和我一起学Windows Workflow Foundation(1)-----创建和调试一个WF实例
  7. [js]js设计模式-构造函数模式
  8. XE5 搭建DataSnap服务
  9. LooseScan Strategy
  10. python桌面程序臃肿_Python自动化整理文件“大升级”,任意路径下文件,都给你整理的明明白白!...
  11. php $stomp write byte message,PHP通过Stomp协议与,ActiveMQ,通信所遇到的问题
  12. unity3d 常用代码
  13. 嵌入式学习笔记-迅为4412开发板实现一键开关机休眠唤醒
  14. 感悟哪吒的故事,我命由我不由天
  15. LaTeX引文.bib方式插入——misplaced alignment tab character . ...ock{\em IEEE Transactions onSystems Man
  16. Received empty response from Zabbix Agent at [agent]. Assuming that agent dropped connection because
  17. 爱琴海的伤感空间日志发布:七月的雨,落得太敷衍
  18. 使用matlab对图像进行傅里叶变换
  19. Adobe Bridge 2021最新中文版来了!!!!
  20. 什么是物联网控制系统?它具有哪些特点?

热门文章

  1. 城市轨道交通运营票务管理论文_城市轨道交通运营企业的票务组织管理
  2. 怎么把geany变成英文_细数Word中英文排版6大坑,我不相信你一个也没有遇到过...
  3. Apache 服务器 参数设置
  4. curl java 转换_Linux CURL学习(转)
  5. (05)System Verilog 组合逻辑与时序逻辑区别
  6. python重命名文件夹下所有文件_Python3.4.3重命名当前文件夹下的文件
  7. 8005.ros2 添加boost库asio编程
  8. clock_gettime系统调用详解
  9. DECLARE_GLOBAL_DATA_PTR
  10. 【c语言】指针数组和数组指针-解释和用法