oracle row_scn,【Oracle概念】-SCN是什么

SCN是什么

SCN查看与转换

ORA_ROWSCN伪列

关于SCN分类

SCN的作用

延伸阅读

SCN是什么

在《Concepts》中是描述SCN的:

A system change number (SCN) is a logical, internal timestamp used by Oracle Database. SCNs order events that occur within the database, which is necessary to satisfy the ACID properties of a transaction. Oracle Database uses SCNs to mark the SCN before which all changes are known to be on disk so that recovery avoids applying unnecessary redo. The database also uses SCNs to mark the point at which no redo exists for a set of data so that recovery can stop.

怎么理解这个“SCN(系统变更号)是供Oracle数据库使用的一个逻辑的、内部的时间戳”呢?要理解这个先需要理解Oracle中的事务(Transaction)和数据一致性(Data Consistency)的概念。

先说说数据一致性的概念。数据一致性指的是数据的可用性。比如说管理一个财务的系统,需要从A账户将100元转入到B账户,正常的操作是从A账户减去100元,然后给B账户加上100元,如果这两步操作都正常完成了,那我们可以说完成转账操作之后的数据是一致可用的;但是如果在操作的过程中出了问题,A账户的100元给减掉了,但是B账户却没有加上100元,这样的情况下产生的结果数据就有问题了,因为部分操作的失败导致了数据的不一致而不可用,在实际中肯定是要避免这种让数据不一致的情况发生的。在Oracle数据库中,保证数据一致性的方法就是事务。

事务是一个逻辑的、原子性的作业单元,通常由一个或者是多个SQL组成,一个事务里面的所有SQL操作要么全部失败回滚(Rollback),要么就是全部成功提交(Commit)。就像上面转账的例子,为保证数据的一致性,就需要将转账的两步操作放在一个事务里面,这样不管哪个操作失败了,都需要将所有已进行的操作回滚,以保证数据的可用性。进行事务管理是数据库区别于别的文件系统的一个最主要的特征,在数据库中事务最主要的作用就是保证了数据的一致性,每次事务的提交都是将数据库从一种一致性的状态带入到另外一种一致性的状态中,SCN就是用来对数据库的每个一致状态进行标记的,每当数据库进入到一个新的一致的状态,SCN就会加1,也就是每个提交操作之后,SCN都会增加。也许你会想为什么不直接记录事务提交时候的时间戳呢?这里面主要是涉及了两个问题,一个是时间戳记录的精度有限,再一个就是在分布式系统中记录时间戳会存在系统时钟同步的问题,详细的讨论可以查看。

SCN在数据库中是一个单一的不断的随着数据库一致性状态的改变而自增的序列。正如一个时间戳代表着时间里面的某一个固定的时刻点一样,每一个SCN值也代表着数据库在运行当中的一个一致性的点,大的SCN值所对应的事务总是比小SCN值的事务发生的更晚。因此把SCN说成是Oracle数据库的逻辑时间戳是很恰当的。

SCN查看与转换

查看系统当前的SCN

Oracle数据库提供了两种直接查看系统当前SCN的方法,一个是V$DATABASE中的CURRENT_SCN列,另外一个就是通过dbms_flashback.get_system_change_number得到。

1

SQL> col scn for 9999999999999

2

SQL> SELECT current_scn scn FROM v$database;

3

4

SCN

5

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

6

7046242302279

1

SQL> col scn for 9999999999999

2

SQL> SELECT DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER scn FROM DUAL;

3

4

SCN

5

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

6

7046242302616

如果你好奇心足够的话也许会执行下面的语句,然后发现一个“惊讶”的结果:

1

SQL> col scn2 for 9999999999999

2

SQL> col scn for 9999999999999

3

SQL> SELECT current_scn scn,

4

DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER scn2

5

FROM v$database;

6

SCN           SCN2

7

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

8

7046253210061  7046253210063

不过请不要惊讶,这个很正常,毕竟语句的执行时需要时间的,虽然很短,不过还是能发生很多的事情。

SCN与时间的相互转换

一个SCN值总是发生在某一个特定的时刻的,只不过由于粒度的不一样,通常会存在多个SCN对应同一个时间戳。Oracle中提供了两个函数以供我们进行SCN和时间的互换:

SCN_TO_TIMESTAMP(scn_number)

将SCN转换成时间戳。

TIMESTAMP_TO_SCN(timestamp)

将时间戳转换成SCN。

下面就举几个例子来说明:

1

-- 将SCN转换成时间戳

2

SQL> SELECT SCN_TO_TIMESTAMP(7046253210061) timestamp FROM DUAL;

3

4

TIMESTAMP

5

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

6

30-MAR-10 10.53.04.000000000 AM

7

8

-- 将时间戳转换成SCN

9

SQL> SELECT TIMESTAMP_TO_SCN(TO_TIMESTAMP('30-MAR-10 10.53.04.000000000 AM',

10

'DD-Mon-RR HH:MI:SS.FF AM')) SCN FROM DUAL;

11

12

SCN

13

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

14

7046253197273

很明显的能看到同样的时间戳,转换出来的SCN就是不一样,其根本原因就是粒度问题了。

ORA_ROWSCN伪列

从10g开始,Oracle提供了一个名为ORA_ROWSCN的伪列来让我们更近距离的接触SCN这个东西,利用这个伪列能很清楚的观察提交(Commit)操作对于表中SCN的影响。

我们先来建立以下测试的数据表和数据(例子延伸自《Oracle9i & 10g编程艺术》一书),下面的例子进行两次,两次唯一的不同在于建表时参数不一样,我们通过这个来观察SCN记录的一些行为。

试验一:

1

-- 建立表

2

CREATE TABLE t ( x INT );

3

4

-- 插入数据

5

BEGIN

6

FOR i IN 1 .. 5

7

LOOP

8

INSERT INTO t VALUES ( i );

9

COMMIT;

10

END LOOP;

11

END;

12

/

13

-- 查看结果

14

SQL> SELECT x, ORA_ROWSCN scn,

15

2  DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) BLOCKNO

16

3  FROM t ORDER BY 2;

17

18

X            SCN    BLOCKNO

19

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

20

1  7046267387297      31002

21

2  7046267387297      31002

22

3  7046267387297      31002

23

4  7046267387297      31002

24

5  7046267387297      31002

试验二:

1

-- 建立表

2

CREATE TABLE t ( x INT ) ROWDEPENDENCIES;

3

4

-- 插入数据

5

BEGIN

6

FOR i in 1 .. 5

7

LOOP

8

INSERT INTO t VALUES ( i );

9

COMMIT;

10

END LOOP;

11

END;

12

/

13

-- 查看结果

14

SQL> SELECT x, ORA_ROWSCN scn,

15

2  DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) blockno

16

3  FROM t ORDER BY 2;

17

18

X            SCN    BLOCKNO

19

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

20

1  7046267390044      31002

21

2  7046267390046      31002

22

3  7046267390047      31002

23

4  7046267390048      31002

24

5  7046267390050      31002

试验一中每行数据的SCN数据都是一样的,如果根据我们现在对SCN的理解的话每次提交之后SCN应该变化才对的,那问题出在哪里呢?问题就出在默认情况下Oracle数据库记录SCN是以数据库为单位记录的,因为在数据库读取数据的时候都是以数据块单位,而不是以行为单位的。

要想达到按行记录SCN就必须在创建表的时候使用参数,ROWDEPENDENCIES用于打开一个数据表的行级的追踪,在行级维护SCN记录,使得我们能清楚的看到每次提交操作对于SCN的影响。试验二就是使用表的ROWDEPENDENCIES特性之后的结果。

ROWDEPENDENCIES有个重要的作用是用来实现乐观锁定(Optimistic Locking),这个在《Oracle9i & 10g编程艺术》一书中有详细的描述。

关于SCN分类

通常看文章的时候能看到各种类型的SCN,但是严格来说SCN是没有分类的,之所以会有不同类型的SCN并不是说这些SCN的概念不一样,而是说不同分类的SCN代表的意义不一样,不管什么时候SCN所指代的都是数据库的某个一致性的状态。就像我们给一天中的某个时间点定义上班时间、另外的某个时间点定义成下班时间一样,数据库Checkpoint发生点的SCN被称为Checkpoint SCN,仅此而已。

下面再列举一些常见的SCN分类:

系统检查点SCN (System Checkpoint SCN)

文件检查点SCN (Datafile Checkpoint SCN)

开始SCN (Start SCN)

结束SCN (Stop SCN)

关于这些不同的SCN的定义环境和作用会在后续备份恢复相关文章中详细说明。

SCN的作用

SCN描述的是数据一致性的状态,自然的它就会在各种涉及数据一致性的场合中起到重要作用的,下面列举的就是其中的一部分:

读数据的一致性

数据库恢复

Flashback

Stream

等等其他的

说这个的原因就是想说SCN在Oracle中的应用无处不在,理解SCN是理解数据库许多其他功能工作原理的基础。

延伸阅读

作者:马齿苋 | 链接:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值