近期要上一个BI的项目,需要对各个业务系统内的数据进行分析,那么问题就来了。现有的数据库中有新insert进来的数据,还会有对于已有的数据进行变更的操作。那么这些新增以及变化都要反应到BI系统中。

可以现有的生产数据库的table中没有可以识别变更的时间戳字段。如果对已有的表增加一个timestmap字段,在数据库层面上当然是非常容易办到的,一个简单的 "alter table add xxx column... " 即可。但是在业务程序方面将会带来巨大的改造量。

  • insert的时候需要多增加一个timestmap字段
  • update的时候需要同时更新timestmap字段

(这样的话,开发人员该疯了)

在MySQL数据库下可以添加一个会自动更新的timestamp。(oracle中不支持该语法)

alter table  t2   add COLUMN T_MODIFY_TM  timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT  'is_timestamp';

在oracle怎么办呢?

伪列ORA_ROWSCN

想啊想,oracle既然存在rownum , rowid 这样的伪列,会不会还有行的scn的伪列呢。。果然oracle有 ---- ORA_ROWSCN

SQL> select * from t2;ID
----------0SQL> select ora_rowscn , id from t2;ORA_ROWSCN         ID
---------- ----------3489228          0SQL> insert into t2 values (2);1 row created.SQL> commit;Commit complete.SQL>  select ora_rowscn , id from t2;ORA_ROWSCN         ID
---------- ----------3489228          03489004          2

为了更方便阅读,还可以把scn的数字转换为时间

SQL> select to_char(scn_to_timestamp(ora_rowscn),'YYYY-MM-DD HH24:MI:SS') , id from t2;TO_CHAR(SCN_TO_TIME         ID
------------------- ----------
2018-02-26 10:40:28          0
2018-02-28 10:35:45          2

Scn转换成时间:

select to_char(scn_to_timestamp(3489228),'YYYY-MM-DD HH24:MI:SS') from dual;

时间转换成scn:

select timestamp_to_scn(to_date('2011-04-14 11:10:25','YYYY-MM-DD HH24:MI:SS')) from dual;

简单的测试,结果很令人开心哈,毕竟不用改程序了。(我为人人做贡献的DBA)

开始在业务测试库中进行验证。

问题1: 遇到了 ORA-08181

ORA-08181: 指定的编号不是有效的系统更改号

ORA-06512: 在 "SYS.SCN_TO_TIMESTAMP", line 1

  1. 00000 - "specified number is not a valid system change number"
    *Cause: supplied scn was beyond the bounds of a valid scn.

*Action: use a valid scn.

刚一到测试系统就遇到了问题。

select  to_char(scn_to_timestamp(ora_rowscn),'YYYY-MM-DD HH24:MI:SS') ,acceptdate , t.* from policycopymain t

原因: 是因为ORA_ROWSCN是一个伪列,这伪列的存在依赖于建表时使用行记录时间跟踪的参数rowdenpendies。
select min(scn) from sys.smon_scn_time ;而min(scn) 最多只能五天内的。因为SMON_SCN_TIME记录5天的数据。

问题2:ora_rowscn不是很准

当我又连续的插入了几行数据的时候,出现了更新一个数据但是好多数据的ora_rowscn都变化为一样的了。

SQL> insert into t2 values (4);1 row created.SQL> insert into t2 values (5);1 row created.SQL> commit;Commit complete.SQL> select to_char(scn_to_timestamp(ora_rowscn),'YYYY-MM-DD HH24:MI:SS') , id from t2;TO_CHAR(SCN_TO_TIME         ID
------------------- ----------
2018-02-26 10:40:28          0
2018-02-28 15:16:18          3
2018-02-28 15:16:18          4
2018-02-28 15:16:18          5SQL> update t2 set id=6 where id=3;1 row updated.SQL> select to_char(scn_to_timestamp(ora_rowscn),'YYYY-MM-DD HH24:MI:SS') , id from t2;TO_CHAR(SCN_TO_TIME         ID
------------------- ----------
2018-02-28 10:40:28          0
2018-02-28 15:16:18          6
2018-02-28 15:16:18          4
2018-02-28 15:16:18          5SQL>  update t2 set id=7 where id=4;1 row updated.SQL> commit;Commit complete.SQL>  select to_char(scn_to_timestamp(ora_rowscn),'YYYY-MM-DD HH24:MI:SS') , id from t2;TO_CHAR(SCN_TO_TIME         ID
------------------- ----------
2018-02-26 10:40:28          0
2018-02-28 15:17:18          6
2018-02-28 15:17:18          7
2018-02-28 15:17:18          5

原因
ora_rowscn分为两种模式:

  • 一种是基于block这是默认的模式(块级跟踪,非行依赖性(NOROWDEPENDENCIES));
  • 一种是基于row上,这种模式只能在建里表时指定ROWDEPENDENCIES(行级跟踪)。

不可以通过后期的alter table语句来将表修改为ROWDEPENDENCIES。

测试

SQL> create table td (id number) rowdependencies;Table created.SQL> insert into td values(1);1 row created.SQL> insert into td values (2);1 row created.SQL> commit;Commit complete.SQL>  select to_char(scn_to_timestamp(ora_rowscn),'YYYY-MM-DD HH24:MI:SS') , id from td;TO_CHAR(SCN_TO_TIME         ID
------------------- ----------
2018-02-28 15:19:46          1
2018-02-28 15:19:46          2SQL> update td set id=3 where id=1;1 row updated.SQL> commit;Commit complete.SQL>  select to_char(scn_to_timestamp(ora_rowscn),'YYYY-MM-DD HH24:MI:SS') , id from td;TO_CHAR(SCN_TO_TIME         ID
------------------- ----------
2018-02-28 15:20:07          3
2018-02-28 15:19:46          2SQL> insert into td values (4);1 row created.SQL> insert into td values (5);1 row created.SQL> commit;Commit complete.SQL>  select to_char(scn_to_timestamp(ora_rowscn),'YYYY-MM-DD HH24:MI:SS') , id from td;TO_CHAR(SCN_TO_TIME         ID
------------------- ----------
2018-02-28 15:20:07          3
2018-02-28 15:19:46          2
2018-02-28 16:16:09          4
2018-02-28 16:16:09          5SQL>
SQL> update td set id=10 where id=4;1 row updated.SQL> commit;Commit complete.SQL>  select to_char(scn_to_timestamp(ora_rowscn),'YYYY-MM-DD HH24:MI:SS') , id from td;TO_CHAR(SCN_TO_TIME         ID
------------------- ----------
2018-02-28 15:20:07          3
2018-02-28 15:19:46          2
2018-02-28 16:16:48         10
2018-02-28 16:16:09          5

在创建表的时候添加了ROWDEPENDENCIES属性还是非常好使的。那

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

问题3 ROWDEPENDENCIES会对数据库带来多少额外的性能影响呢

SQL> oradebug setmypid;
Statement processed.
SQL> oradebug tracefile_name;
/s01/10gdb/admin/clinica/udump/clinica_ora_12934.trcblock_row_dump:
tab 0, row 0, @0x1f88
tl: 24 fb: --H-FL-- lb: 0x0  cc: 2
dscn 0x0000.0351b8bd
col  0: [ 2]  c1 02
col  1: [11]  78 6f 01 02 15 20 1a 21 d8 52 68
tab 0, row 1, @0x1f70
tl: 24 fb: --H-FL-- lb: 0x0  cc: 2
dscn 0x0000.0351b8c4
col  0: [ 2]  c1 03
col  1: [11]  78 6f 01 02 15 20 26 02 ab c2 f8

/* 可以从block dump中看到每行都多出了dscn信息,这就是基于行追踪的行级ORA_ROWSCN信息的来源。
注意这里的dscn需要占用6个字节的空间,换而言之启用ROWDEPENDENCIES会为每一行多出6个字节的磁盘开销。
/ 此部分摘自 MACLEAN LIU
http://www.askmaclean.com/archives/%E5%9F%BA%E4%BA%8E%E8%A1%8C%E8%B7%9F%E8%B8%AA%E7%9A%84rowdependencies-ora_rowscn%E4%BF%A1%E6%81%AF.html

那么1千万行的数据,将会有10m存储容量的开销

关于获取oracle中数据变更的时间戳的探索(待更新)相关推荐

  1. 使用JPA获取Oracle中的日期字段丢失时分秒

    2019独角兽企业重金招聘Python工程师标准>>> 使用JPA获取oracle中的日期字段发现没有时分秒,因为之前没有关注过这个字段, 最近由于需要,却发现时分秒奇怪的丢失.   ...

  2. mysql clob转string_Java获取Oracle中CLOB字段转换成String

    Java获取Oracle中CLOB字段转换成String : try {PreparedStatement stmt = session.connection().prepareStatement(s ...

  3. php 获取数据库中的信息,php获取数据库中数据的实现方法

    废话不多说,直接上代码 header("Content-type:text/html;charset=utf-8");//字符编码设置 $servername = "lo ...

  4. python如何复制oracle数据_Python使用cx_Oracle模块将oracle中数据导出到csv文件的方法...

    本文实例讲述了Python使用cx_Oracle模块将oracle中数据导出到csv文件的方法.分享给大家供大家参考.具体实现方法如下: # Export Oracle database tables ...

  5. java Clob转CLOB_Java获取Oracle中CLOB字段转换成String

    Java获取Oracle中CLOB字段转换成String : try {PreparedStatement stmt = session.connection().prepareStatement(s ...

  6. 视图中获取控制器中数据的方式

    在视图中获取控制器中数据的方式有两种: 一种是在控制器的操作中渲染视图时候分配模板数据,这种方式叫推送. 另外一种是在视图中手动获取控制器中的数据,包括控制器中的属性和方法及控制器id,通过$this ...

  7. 通过js获取Model中数据

    通过js获取Model中数据 前端js获取model 1.获取model的js代码必须写在html中 2.script中添加 th:inline="javascript" < ...

  8. sql获取oracle数据库数据,通过sql语句获取数据库的基本信息

    您可以通过以下几个sql 可以立即了解系统的状况和数据库的状态(仅献给习惯使用sql/plus的人 呵呵 ) (1) 查询oracle 的物理结构 1.1. 查看数据文件 SQL> select ...

  9. oracle中数据导入导出问题

    在日常生活中,我们有时难免要对一些系统进行移植,移植的时候,数据库中的数据问题就需要在不同的服务器上移动,这时就涉 及到数据的导入导出问题,这里我给大家介绍一些oracle数据的导入和导出问题. or ...

最新文章

  1. 爬虫原理与数据抓取----- urllib2:URLError与HTTPError
  2. C++简单使用Jsoncpp来读取写入json文件
  3. 阿里巴巴开源容器镜像加速技术
  4. datax 模板_datax模板
  5. 51单片机点亮数码管
  6. extjs4 冻结列_extjs4 事件处理
  7. 搞不明白为什么大家都在学习 k8s
  8. 趣学 C 语言(九)—— 复杂指针解析
  9. 设计模式---外观模式(C++实现)
  10. 接口与事件之图形界面的认证登录
  11. 计算机系统操作工中级工试卷,计算机系统操作工中级理论试题及答案.doc
  12. matlab如何插入“埃”这个符号
  13. Word2Vec实战
  14. JS 网页设置横竖屏切换
  15. 隐藏label标签中指定文字
  16. 人机耦合,让AI转人工更有价值
  17. 解决osm移动地图shp图层消失问题
  18. 微软针对lapsus$事件的最新调查报告 中文版
  19. Vue报错:component has been registered but not used
  20. mysql中的 isnull(exper)、ifnull(exper1,exper2)、nullif(exper1,exper2)函数

热门文章

  1. 你画我猜微擎版小程序源码
  2. Spcok简约图片分享网站Typecho主题
  3. emlog和typecho文章采集插件-简数第三方数据采集
  4. Bandicam_v4.6.5便携特别版 高清视频录制工具
  5. java导入项目存在,如何将预先存在的Java项目导入Eclipse并启动并运行?
  6. C# | C#中变量(局部变量)的声明和范围
  7. mysql安装忘了root_MySQL - 安装:MySQL忘记root密码的解决办法
  8. MSSQL 2005数据库安全设置
  9. Text Link Ads 注册[赚钱一]
  10. Think in AngularJS :对比 jQuery 和 AngularJS 的不同思维模式