近期要上一个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;
----------
SQL> select ora_rowscn , id from t2;
ORA_ROWSCN ID
---------- ----------
3489228 0
SQL> insert into t2 values (2);
1 row created.
SQL> commit;
Commit complete.
SQL> select ora_rowscn , id from t2;
ORA_ROWSCN ID
---------- ----------
3489228 0
3489004 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 108181. 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 5
TO_CHAR(SCN_TO_TIME ID
------------------- ----------
2018-02-28 10:40:28 0
2018-02-28 15:16:18 6 ==>3
2018-02-28 15:16:18 4
2018-02-28 15:16:18 5
SQL> 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 ==>4
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.
TO_CHAR(SCN_TO_TIME ID
------------------- ----------
2018-02-28 15:19:46 1
2018-02-28 15:19:46 2 ===>same
SQL> 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 ==> 1
2018-02-28 15:19:46 2
SQL> 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 5
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 ==>4
2018-02-28 16:16:09 5
Statement processed.
SQL> oradebug tracefile_name;
/s01/10gdb/admin/clinica/udump/clinica_ora_12934.trc
block_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个字节的磁盘开销。
近期要上一个BI的项目,需要对各个业务系统内的数据进行分析,那么问题就来了。现有的数据库中有新insert进来的数据,还会有对于已有的数据进行变更的操作。那么这些新增以及变化都要反应到BI系统中。可以现有的生产数据库的table中没有可以识别变更的时间戳字段。如果对已有的表增加一个timestmap字段,在数据库层面上当然是非常容易办到的,一个简单的 "alter table add xxx c...
SQL> SELECT SCN_TO_TIMESTAMP(ORA_ROWSCN) FROM emp;
SELECT SCN_TO_TIMESTAMP(ORA_ROWSCN) FROM dept
ERROR ...
oerr ora 08181
08181, 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.
oerr ora 06512
06512, 00000, "at %sline %s"
// *Cause: Backtrace message as th
9i的闪回查询特性:
闪回功能依赖的于回滚段中存储的数据前镜像 ,在9前版本中,通常只要事物提交后,前镜像数据就可以被覆盖,
空间可以重用;9中引入了自动回滚段管理,可以通过调整UNDO_RETENTION参数来设置数据库UNDO信息的保留时间,
只要前镜像没有被覆盖,那么闪回就是可能的,但要注意,UNDO信息的保留还同UNDO表空间的空间有关,如空间紧张,
为了满足事物需要,非活动...
select dbms_flashback.get_system_change_number FROM dual;
select * FROM tablename as of scn 13248629807;
insert int...
在 Java
中,可以使用 `Instant` 类来
获取指定时间的
时间戳。
首先,你需要使用 `ZonedDateTime` 类来表示指定的时间。你可以使用 `ZonedDateTime.of` 方法来创建一个 `ZonedDateTime` 对象,并传入时间的年份、月份、日期、小时数、分钟数、秒数和时区信息:
```java
ZonedDateTime zonedDateTime = ZonedDateTime.of(2020, 1, 1, 0, 0, 0, 0, ZoneId.of("Asia/Shanghai"));
然后,你可以使用 `Instant` 类的 `from` 方法来将 `ZonedDateTime` 对象转换为
时间戳:
```java
Instant instant = Instant.from(zonedDateTime);
long timestamp = instant.toEpochMilli();
最后,你可以使用 `toEpochMilli` 方法将 `Instant` 对象转换为毫秒级
时间戳。
注意,
时间戳是从 1970 年 1 月 1 日 00:00:00 开始计算的。
例如,下面是一个完整的示例,展示了如何
获取指定时间的
时间戳:
```java
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
// 创建 ZonedDateTime 对象
ZonedDateTime zonedDateTime = ZonedDateTime.of(2020, 1, 1, 0, 0, 0, 0, ZoneId.of("Asia/Shanghai"));
// 将 ZonedDateTime 对象转换为
时间戳
Instant instant = Instant.from(zonedDateTime);
long timestamp = instant.toEpochMilli();
System.out.println(timestamp); // 输出 1577836800000
ORA-27124: Unable To Detach From Shared Memory Segment & IBM AIX RISC System/6000 Error: 22: Invalid
AIX unzip 解压遇到 End-of-central-directory signature not found. Either this file is not a zipfile
达梦日常运维日常SQL(持续更新ing)