【体系结构】有关Oracle SCN知识点的整理--补充内容

简介: 【体系结构】有关Oracle SCN知识点的整理--补充内容   小麦苗自己整理的内容参考:【体系结构】有关Oracle SCN知识点的整理  http://blog.itpub.net/26736162/viewspace-2126407/ DBA入门之认识Oracle SCN(System Change Number) 1. SCN的定义 SCN(System Change Number),也就是通常所说的系统改变号,是数据库中非常重要的一个数据结构。

【体系结构】有关Oracle SCN知识点的整理--补充内容




  小麦苗自己整理的内容参考:【体系结构】有关Oracle SCN知识点的整理  http://blog.itpub.net/26736162/viewspace-2126407/





DBA入门之认识Oracle SCN(System Change Number)

1. SCN的定义

SCN(System Change Number),也就是通常所说的系统改变号,是数据库中非常重要的一个数据结构。

SCN用以标识数据库在某个确切时刻提交的版本。在事务提交时,它被赋予一个唯一的标识事务的SCN。SCN同时被作为Oracle数据库的内部时钟机制,可被看做逻辑时钟,每个数据库都有一个全局的SCN生成器。

作为数据库内部的逻辑时钟,数据库事务依SCN而排序,Oracle也依据SCN来实现一致性读(Read Consistency)等重要数据库功能。另外对于分布式事务(Distributed Transactions),SCN也极为重要,这里不做更多介绍。

SCN在数据库中是唯一的,并随时间而增加,但是可能并不连贯。除非重建数据库,SCN的值永远不会被重置为0.

一直以来,对于SCN有很多争议,很多人认为SCN是指System Commit Number,而通常SCN在提交时才变化,所以很多时候,这两个名词经常在文档中反复出现。即使在Oracle的官方文档中,SCN也常以System Change/Commit Number两种形式出现。

到底是哪个词其实不是很重要,重要的是需要知道SCN是Oracle内部的时钟机制,Oracle通过SCN来维护数据库的一致性,并通过SCN实施Oracle至关重要的恢复机制。

SCN在数据库中是无处不在,常见的事务表、控制文件、数据文件头、日志文件、数据块头等都记录有SCN值。

冠以不同前缀,SCN也有了不同的名称,如检查点SCN(Checkpint SCN)、Resetlogs SCN等。

 

2.SCN的获取方式

可以通过如下几种方式获得数据库的当前或近似SCN。

(1) 从Oracle 9i开始。

可以使用dbms_flashback.get_system_change_number来获得:

SQL> select dbms_flashback.get_system_change_number from dual;

GET_SYSTEM_CHANGE_NUMBER

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

888266

(2) Oracle 9i前。

可以通过查询x$ktuxe获得系统最接近当前值的SCN:

X$ktuxe的含义是[k]ernel [T]ransaction [U]ndo Transa[x]tion [E]ntry(table)

SQL>select max(ktuxecnw*power(2,32)+ktuxescnb) from x$ktuxe;

MAX(KTUXESCNW*POWER(2,32)+KTUXESCNB)

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

28848232

 

3.SCN的进一步说明

系统当前SCN并不是在任何的数据库操作时都会改变,SCN通常在事务提交或回滚时改变。在控制文件、数据文件头、数据库、日志文件头、日志文件change vector中都有SCN,但其作用各不相同。

(1) 数据文件头中包含了该数据文件的Checkpoint SCN,表示该数据文件最近一次执行检查点操作时的SCN

从控制文件的dump文件中,可以得到一下内容:

DATA FILE #1:

(name #7) /opt/ora10g/oradata/ORCL/system01.dbf

creation size=0 block size=8192 status=0xe head=7 tail=7 dup=1

tablespace 0, index=1 krfil=1 prev_file=0

unrecoverable scn: 0x0000.00000000 01/01/1988 00:00:00

Checkpoint cnt:106 scn: 0x0000.000d845f 11/14/2011 15:24:50

Stop scn: 0xffff.ffffffff 11/14/2011 14:31:00

Creation Checkpointed at scn: 0x0000.00000009 06/30/2005 19:10:11

……

对于每一个数据文件都包含一个这样的条目,记录该文件的检查点SCN的值以及检查点发生的时间,这里的Checkpint SCN、Stop SCN以及Checkpoint CNT都是非常重要的数据结构,我们将会在下面检查点部分详细介绍。

同样可以通过命令转储数据文件头,观察其具体信息及检查点记录等,从跟踪文件中摘取system表空间的记录作为参考:

***************************************************************************

DATA FILE RECORDS

***************************************************************************

(size = 428, compat size = 428, section max = 100, section in-use = 4,

last-recid= 53, old-recno = 0, last-recno = 0)

(extent = 1, blkno = 11, numrecs = 100)

DATA FILE #1:

(name #7) /opt/ora10g/oradata/ORCL/system01.dbf

creation size=0 block size=8192 status=0xe head=7 tail=7 dup=1

tablespace 0, index=1 krfil=1 prev_file=0

unrecoverable scn: 0x0000.00000000 01/01/1988 00:00:00

Checkpoint cnt:106 scn: 0x0000.000d845f 11/14/2011 15:24:50

Stop scn: 0xffff.ffffffff 11/14/2011 14:31:00

Creation Checkpointed at scn: 0x0000.00000009 06/30/2005 19:10:11

thread:0 rba:(0x0.0.0)

enabled threads: 00000000 00000000 00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

Offline scn: 0x0000.0006ce7a prev_range: 0

Online Checkpointed at scn: 0x0000.0006ce7b 11/10/2011 22:40:23

thread:1 rba:(0x1.2.0)

enabled threads: 01000000 00000000 00000000 00000000 00000000 00000000

Hot Backup end marker scn: 0x0000.00000000

aux_file is NOT DEFINED

(2) 日志文件头包含了Low SCN 和Next SCN。

Low SCN和 Next SCN这两个SCN表示该日志文件包含介于Low SCN到Next SCN的重做信息,对于Current的日志文件(当前正在被使用的Redo Logfile),其最终SCN不可知,所以Next SCN被置为无穷大,也就是ffffffff。

来看一下日志文件的情况:

SQL> select * from v$log;

GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIM

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

1 1 35 52428800 1 NO CURRENT 881890 14-NOV-11

2 1 33 52428800 1 YES INACTIVE 836815 12-NOV-11

3 1 34 52428800 1 YES INACTIVE 858362 12-NOV-11

SQL> select dbms_flashback.get_system_change_number from dual;

GET_SYSTEM_CHANGE_NUMBER

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

889346

SQL> alter system switch logfile;

System altered.

SQL> select * from v$log;

GROUP# THREAD# SEQUENCE# BYTES MEMBERS ARC STATUS FIRST_CHANGE# FIRST_TIM

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

1 1 35 52428800 1 YES ACTIVE 881890 14-NOV-11

2 1 36 52428800 1 NO CURRENT 889353 14-NOV-11

3 1 34 52428800 1 YES INACTIVE 858362 12-NOV-11

可以看到,SCN 889346显然位于Log Group#为1的日志文件中,该日志文件包含了SCN自881890 至889353 的Redo信息。Oracle在进行恢复时,就需要根据低SCN和高SCN来确定需要的恢复信息位于哪一个日志或归档文件中。

如果通过控制文件转储,可以在控制文件中找到关于日志文件的信息:

SQL> alter session set events 'immediate trace name redohdr level 10';

Session altered.

 

LOG FILE #1:

(name #3) /opt/ora10g/oradata/ORCL/redo01.log

Thread 1 redo log links: forward: 2 backward: 0

siz: 0x19000 seq: 0x00000026 hws: 0x1 bsz: 512 nab: 0xffffffff flg: 0x8 dup: 1

Archive links: fwrd: 0 back: 0 Prev scn: 0x0000.000de15c

Low scn: 0x0000.000def9a 11/16/2011 16:06:06

Next scn: 0xffff.ffffffff 01/01/1988 00:00:00

LOG FILE #2:

(name #2) /opt/ora10g/oradata/ORCL/redo02.log

Thread 1 redo log links: forward: 3 backward: 1

siz: 0x19000 seq: 0x00000024 hws: 0x4 bsz: 512 nab: 0x5c6 flg: 0x1 dup: 1

Archive links: fwrd: 0 back: 0 Prev scn: 0x0000.000d74e2

Low scn: 0x0000.000d9209 11/14/2011 16:57:08

Next scn: 0x0000.000de15c 11/16/2011 15:01:07

LOG FILE #3:

(name #1) /opt/ora10g/oradata/ORCL/redo03.log

Thread 1 redo log links: forward: 0 backward: 2

siz: 0x19000 seq: 0x00000025 hws: 0x3 bsz: 512 nab: 0x37e3 flg: 0x1 dup: 1

Archive links: fwrd: 0 back: 0 Prev scn: 0x0000.000d9209

Low scn: 0x0000.000de15c 11/16/2011 15:01:07

Next scn: 0x0000.000def9a 11/16/2011 16:06:06

可以注意到,Log File 1是当前的日志文件,该文件拥有的Next SCN是无穷大。

同样,可以通过直接dump日志文件的方式来进行转储;

SQL> select * from v$logfile;

GROUP# STATUS TYPE MEMBER

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

3 ONLINE /opt/ora10g/oradata/ORCL/redo03.log

2 ONLINE /opt/ora10g/oradata/ORCL/redo02.log

1 ONLINE /opt/ora10g/oradata/ORCL/redo01.log

SQL> alter system dump logfile '/opt/ora10g/oradata/ORCL/redo01.log';

System altered.

DUMP OF REDO FROM FILE '/opt/ora10g/oradata/ORCL/redo01.log'

Opcodes *.*

RBAs: 0x000000.00000000.0000 thru 0xffffffff.ffffffff.ffff

SCNs: scn: 0x0000.00000000 thru scn: 0xffff.ffffffff

Times: creation thru eternity

FILE HEADER:

Compatibility Vsn = 169869568=0xa200100

Db ID=1294662348=0x4d2afacc, Db Name='ORCL'

Activation ID=1294635980=0x4d2a93cc

Control Seq=953=0x3b9, File size=102400=0x19000

File Number=1, Blksiz=512, File Type=2 LOG

descrip:"Thread 0001, Seq# 0000000038, SCN 0x0000000def9a-0xffffffffffff"

thread: 1 nab: 0xffffffff seq: 0x00000026 hws: 0x1 eot: 1 dis: 0

resetlogs count: 0x2db5af57 scn: 0x0000.0006ce7b (446075)

resetlogs terminal rcv count: 0x0 scn: 0x0000.00000000

prev resetlogs count: 0x2184ef74 scn: 0x0000.00000001 (1)

prev resetlogs terminal rcv count: 0x0 scn: 0x0000.00000000

Low scn: 0x0000.000def9a (913306) 11/16/2011 16:06:06

Next scn: 0xffff.ffffffff 01/01/1988 00:00:00

Enabled scn: 0x0000.0006ce7b (446075) 11/10/2011 22:40:23

Thread closed scn: 0x0000.000def9a (913306) 11/16/2011 16:06:06

Disk cksum: 0x5987 Calc cksum: 0x5987

Terminal recovery stop scn: 0x0000.00000000

Terminal recovery 01/01/1988 00:00:00

Most recent redo scn: 0x0000.00000000

Largest LWN: 0 blocks

End-of-redo stream : No

Unprotected mode

Miscellaneous flags: 0x0

这里不打算详细介绍具体命令的用户及更进一步的内容,有兴趣的朋友可以由此开始进一步的探索。



使用Oradebug修改Oracle SCN  

Oracle SCN对于数据库运行、维护而言是至关重要的因素。在启动从mountopen过程中,主要是各种文件的SCN进行比较的行为。通常情况下,我们是不需要介入到Oracle SCN的取值和设置,甚至错误的干预可能会引起严重运行事故。

 

在之前的文章中,笔者介绍过使用隐含参数和跟踪事件来推动Oracle SCN前进的方法。但是,在11.2.0.2之后的版本中,Oracle关闭了这个通道,这种方法不在有效。在高版本情况下,我们是可以通过oradebug工具对SCN进行修改。

 

注意:这种方法比较危险,请不要在投产环境下进行测试。

 

1、实验环境说明

 

笔者使用Oracle 11g进行测试,版本为11.2.0.4。对应操作系统是Linux 6.5 64bit版本。

 

 

SQL> select * from v$version;

 

BANNER

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

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

PL/SQL Release 11.2.0.4.0 - Production

CORE    11.2.0.4.0      Production

TNS for Linux: Version 11.2.0.4.0 - Production

NLSRTL Version 11.2.0.4.0 – Production

 

 

我们先聊聊OracleSCN。在数据库内部,SCN是一个单向递增的数字编号,控制文件、数据文件、在线Redo日志、归档日志和备份集合中,都包括这个数字编号。在内部文件中,SCN是通过BaseWrap两个部分进行保存。BaseSCN编号的基础位,是通过32位二进制位进行保存。一旦超过这32位长度,系统会自动在Wrap进位。也就是说,Wrap表示的超过4G个数的进位次数。

 

使用Oracle oradebug修改SCN,可以在两个场景下进行,就是Oracle启动Open状态和Mount状态。下面分别进行说明。

 

2Open状态下SCN修改

 

Open状态,系统的SCN是在不断的向前推动,即使对外没有事务操作,系统内部SCN编号也在不断的前进。我们先将数据库进入open状态。

 

 

SQL> alter database open;

Database altered.

 

SQL> select CHECKPOINT_CHANGE#, current_scn from v$database;

 

CHECKPOINT_CHANGE# CURRENT_SCN

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

           1753982     1754355

 

SQL> select dbms_flashback.get_system_change_number from dual;

 

GET_SYSTEM_CHANGE_NUMBER

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

                 1754364

 

 

此时,从系统中提取出的SCN编号约为1754364,显然没有超过wrap的进位4G,变化为16进制如下:

 

 

SQL> select to_char(1754364, 'XXXXXXXX') from dual;

 

TO_CHAR(1754364,'XXXXXXXX')

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

   1AC4FC

 

 

使用oradebug查看内存中SCN对应的变量。

 

 

SQL> oradebug setmypid

Statement processed.

SQL> oradebug dumpvar sga kcsgscn_                      

kcslf kcsgscn_ [06001AE70, 06001AEA0) = 001AC52A 00000000 00000000 00000000 00000065 00000000 00000000 00000000 00000000 00000000 6001AB50 00000000

 

 

其中,0x001AC52A近似SCNBase部分。注意:Linux系统是Little位的操作系统,Base在前,Wrap在后。

 

 

SQL> select to_number('1AC52A','xxxxxx') from dual;

 

TO_NUMBER('1AC52A','XXXXXX')

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

                     1754410

 

 

下面计划将Base修改为1800000,查看16进制取值。

 

 

SQL> select to_char(1800000, 'XXXXXXXX') from dual;

 

TO_CHAR(1800000,'XXXXXXXX')

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

   1B7740

 

 

使用poke命令将计算好的值写入进去。

 

 

SQL> oradebug poke 0x06001AE70 4 0x001B7740

BEFORE: [06001AE70, 06001AE74) = 001AC66F

AFTER:  [06001AE70, 06001AE74) = 001B7740

SQL> oradebug DUMPvar SGA kcsgscn_

kcslf kcsgscn_ [06001AE70, 06001AEA0) = 001B7745 00000000 00000000 00000000 00000164 00000000 00000000 00000000 00000000 00000000 6001AB50 00000000

SQL>

 

 

poke命令中,第一位参数是对应写入的内存位数,第二位参数是写入长度,第三位参数是写入取值。默认写入取值是10进制,我们在这里指定写入16进制。

 

每一个取值段,用816进制对应,对应到数字位数是4位。此时查看Oracle情况。

 

 

SQL> select CHECKPOINT_CHANGE#, current_scn from v$database;

 

CHECKPOINT_CHANGE# CURRENT_SCN

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

           1753982     1800400

 

SQL> select dbms_flashback.get_system_change_number from dual;

 

GET_SYSTEM_CHANGE_NUMBER

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

                 1800402

 

 

SQL> select file#, checkpoint_change# from v$datafile;

 

     FILE# CHECKPOINT_CHANGE#

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

         1            1753982

         2            1753982

         3            1753982

         4            1753982

         5            1753982

         6            1753982

         7            1753982

 

7 rows selected

 

SQL> select file#, checkpoint_change# from v$datafile_header;

 

     FILE# CHECKPOINT_CHANGE#

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

         1            1753982

         2            1753982

         3            1753982

         4            1753982

         5            1753982

         6            1753982

         7            1753982

 

7 rows selected

 

 

从上面看,内存和控制文件中新的取值已经写入进去了。但是各个文件的头块和检查点还没有反应过来。此时可以使用checkpoint强制写入。

 

 

SQL> alter system checkpoint;

System altered.

 

SQL> select file#, checkpoint_change# from v$datafile;

 

     FILE# CHECKPOINT_CHANGE#

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

         1            1800422

         2            1800422

         3            1800422

         4            1800422

         5            1800422

         6            1800422

         7            1800422

 

7 rows selected

 

SQL> select file#, checkpoint_change# from v$datafile_header;

 

     FILE# CHECKPOINT_CHANGE#

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

         1            1800422

         2            1800422

         3            1800422

         4            1800422

         5            1800422

         6            1800422

         7            1800422

 

7 rows selected

 

SQL> select CHECKPOINT_CHANGE#, current_scn from v$database;

 

CHECKPOINT_CHANGE# CURRENT_SCN

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

           1800422     1800433

 

 

此时,关闭重启系统也不会有问题。篇幅原因,不进行具体展示。那么,很多时候SCN错误是会影响到开启数据库的,我们可能都不能进入open状态。从mount状态下我们怎么修改SCN编号。

 

3Mount状态修改SCN编号

 

我们测试进入mount状态。

 

 

SQL> startup mount

ORACLE instance started.

 

Total System Global Area 3540881408 bytes

Fixed Size                  2258320 bytes

Variable Size             855640688 bytes

Database Buffers         2667577344 bytes

Redo Buffers               15405056 bytes

Database mounted.

 

 

此时,oradebug命令导出内存取值。

 

 

SQL> oradebug setmypid

Statement processed.

SQL> oradebug DUMPvar SGA kcsgscn_

kcslf kcsgscn_ [06001AE70, 06001AEA0) = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 6001AB50 00000000

 

 

注意:在mount状态下,内存中的SCN取值都是0,包括basewrap两部分。我们这次修改wrap01。这个过程中,我们需要写入basewrap两个部分,如果我们只写入了wrap部分,base部分保持0,那么系统运行的时候,会从base0开始。

 

此时,需要查看一下当前文件里面SCN是多少。

 

 

SQL> select file#, checkpoint_change# from v$datafile;

 

     FILE# CHECKPOINT_CHANGE#

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

         1            1800920

         2            1800920

         3            1800920

         4            1800920

         5            1800920

         6            1800920

         7            1800920

 

7 rows selected

 

SQL> select file#, checkpoint_change# from v$datafile_header;

 

     FILE# CHECKPOINT_CHANGE#

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

         1            1800920

         2            1800920

         3            1800920

         4            1800920

         5            1800920

         6            1800920

         7            1800920

 

7 rows selected

 

SQL> select CHECKPOINT_CHANGE#, current_scn from v$database;

 

CHECKPOINT_CHANGE# CURRENT_SCN

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

           1800920           0

 

 

计算1800920对应到16进制取值为:0x001B7AD8。下面分别写入basewrap取值。

 

 

SQL> oradebug DUMPvar SGA kcsgscn_

kcslf kcsgscn_ [06001AE70, 06001AEA0) = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 6001AB50 00000000

SQL> oradebug poke 0x06001AE70 4 0x001B7AD8

BEFORE: [06001AE70, 06001AE74) = 00000000

AFTER:  [06001AE70, 06001AE74) = 001B7AD8

SQL> oradebug poke 0x06001AE74 4 0x00000001

BEFORE: [06001AE74, 06001AE78) = 00000000

AFTER:  [06001AE74, 06001AE78) = 00000001

SQL> oradebug DUMPvar SGA kcsgscn_

kcslf kcsgscn_ [06001AE70, 06001AEA0) = 001B7AD8 00000001 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 6001AB50 00000000

 

 

启动数据库。

 

 

SQL> alter database open;

Database altered.

 

SQL> select CHECKPOINT_CHANGE#, current_scn from v$database;

 

CHECKPOINT_CHANGE# CURRENT_SCN

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

        4296768217  4296768485

 

SQL> select file#, checkpoint_change# from v$datafile_header;

 

     FILE# CHECKPOINT_CHANGE#

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

         1         4296768217

         2         4296768217

         3         4296768217

         4         4296768217

         5         4296768217

         6         4296768217

         7         4296768217

 

7 rows selected

 

SQL> select file#, checkpoint_change# from v$datafile;

 

     FILE# CHECKPOINT_CHANGE#

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

         1         4296768217

         2         4296768217

         3         4296768217

         4         4296768217

         5         4296768217

         6         4296768217

         7         4296768217

 

7 rows selected

 

 

显然在open的时候,写入的checkpoint在所有文件中。写入的wrap头也比较清晰。

 

 

SQL> select 4296768217/(4*1024*1024*1024) from dual;

 

4296768217/(4*1024*1024*1024)

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

              1.0004193095956

 

SQL> oradebug DUMPvar SGA kcsgscn_

kcslf kcsgscn_ [06001AE70, 06001AEA0) = 001B7C1D 00000001 00000000 00000000 00000047 00000000 00000000 00000000 00000000 00000000 6001AB50 00000000

 

 

4、结论

 

使用oradebug直接修改内存SCN,是我们在故障修复时候非常快捷的方法。不过,快捷建立在对内部机制清晰理解的前提之下。所以,无论何种场景进行修复,有备份、可恢复是我们工作的基本前提。

 



Oracle系统表 smon_scn_time 的说明

一.SMON_SCN_TIME 表结构说明

 

SMON_SCN_TIME表存放的是SCN和Time之前的映射关系。 该表由SMON 进程负责维护。

 

SQL> desc smon_scn_time

 Name                                     Null?    Type

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

 THREAD                                            NUMBER

 TIME_MP                                            NUMBER

 TIME_DP                                           DATE

 SCN_WRP                                           NUMBER

 SCN_BAS                                           NUMBER

 NUM_MAPPINGS                                       NUMBER

 TIM_SCN_MAP                                       RAW(1200)

 SCN                                               NUMBER

 ORIG_THREAD                                        NUMBER

 

SQL> alter session set nls_date_format='yyyy-mm-ddhh24:mi:ss';

Session altered.

 

SQL> select time_dp,scn from smon_scn_time where rownum<5;

TIME_DP                    SCN

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

2013-03-15 10:31:04    2092348

2013-03-15 10:35:49    2092452

2013-03-15 10:41:00    2092581

2013-03-15 10:45:46    2092682

 

 

在Oracle 11g中,该表的创建SQL在$ORACLE_HOME/rdbms/admin/dtxnspc.bsq 文件中。

 

create table smon_scn_time (

 thread number,                        /* thread, compatibility */

 time_mp number,                       /* time this recent scn represents */

 time_dp date,                         /* time as date, compatibility */

  scn_wrpnumber,                        /*scn.wrp, compatibility */

 scn_bas number,                       /* scn.bas, compatibility */

 num_mappings number,

 tim_scn_map raw(1200),

  scnnumber default 0,                  /* scn*/

 orig_thread number default 0          /* for downgrade */

) cluster smon_scn_to_time_aux (thread)

/

create unique index smon_scn_time_tim_idxon smon_scn_time(time_mp)

 tablespace SYSAUX

/

create unique index smon_scn_time_scn_idxon smon_scn_time(scn)

 tablespace SYSAUX

/

 

我们可以直接delete掉SMON_SCN_TIME表中的记录:

SQL> delete from smon_scn_time;

2120 rows deleted.

 

SQL> commit;

Commit complete.

 

SQL> select count(1) from smon_scn_time;

 COUNT(1)

----------

        0

 

 

二.SMON_SCN_TIME表记录保存策略说明

 

2.1 Oracle 9i

 

根据MOS文档的说明:

How To Map SCN To Timestamp Before 10g? [ID365536.1]

 

SYS.SMON_SCN_TIMEwill have a maximum of 1440 rows and each record will be for a 5 minute period.Oracle maintains this information for a maximum of 5 days after which therecords will be recycled.

 

This means thatdata is stored 12 times per hour * 24 hours * 5 days = 1440 rows.  

 

    在Oracle 9i版本中,SMON_SCN_TIME 表中最多存放1440条记录。 SMON 进程每隔5分钟生成一次SCN和TIME 之前的映射,并更新到SMON_SCN_TIME表。该表的维护周期是5天。

    因此该表最多存放的记录是:12*24*5=1440条记录。

 

    超过1440条的记录在下次循环中会被删除。

 

 

2.2 Oracle 10g以后的版本

    在oracle 10g以后的版本,SMON_SCN_TIME表的维护策略发生了变化。

 

根据MOS文档的说明:

High Executions Of Statement "deletefrom smon_scn_time..." [ID 375401.1]

 

The deletestatement deletes the oldest rows from smon_scn_time to clear space for newrows.  SMON wakes up every 5 minutes and checks how many on-disk mappingswe have--the max is 144000.

    --SMON进程每个5分钟唤醒一次来更新SCN和TIME之间的映射关系,并且检查SMON_SCN_TIME表中的记录数,该表的记录数最大是144000条。

 

The new mappingsare then added for the last period (since SMON last updated), and if this isover 144000, SMON will then issue the delete statement:

delete fromsmon_scn_time where thread=0 and time_mp = (select min(time_mp) fromsmon_scn_time where thread=0)

    --SMON进程会把最新的SCN_TIME映射关系写入SMON_SCN_TIME表,如果该表的记录数超过144000条,那么就会执行上面的delete操作,删除最早的记录。

 

There will be anexecution of this each time SMON wakes to update smon_scn_time, and if onedeletion does not free enough mappings, then there will be multiple executions.

--SMON进程每次被唤醒都会更新SMON_SCN_TIME表,如果一次delete操作不能释放足够的空间映射空间,就会执行多次delete操作。

 

 

三.禁用SMON 进程对SMON_SCN_TIME 表的更新

 

可以设置12500事件停止SMON进程对SMON_SCN_TIME。

 

具体操作如下:

 

SQL> select count(1) from smon_scn_time;

 

 COUNT(1)

----------

     2115

 

SQL> alter system set events '12500trace name context forever, level 10';

System altered.

 

SQL> select sysdate from dual;

SYSDATE

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

2013-03-20 13:06:15

 

SQL> select count(1) from smon_scn_time;

 

 COUNT(1)

----------

     2115

 

SQL> alter system set events '12500 tracename context off';

System altered.

 

SQL> select sysdate from dual;

SYSDATE

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

2013-03-20 13:19:58

 

SQL> select count(1) from smon_scn_time;

 COUNT(1)

----------

     2119

 

 

 

 

四.SMON_SCN_TIME 表相关的2个案例

 

 

4.1 Oracle 9i SMON_SCN_TIME 表被锁

 

LOCK ON SYS.SMON_SCN_TIME [ID 747745.1]

 

4.1.1 现象

Oracle 9i,SYS.SMON_SCN_TIME 被 SMON 进程已排它锁占用,并且锁不能释放,导致数据库出现性能问题,并且SMON_SCN_TIME表中有大量的记录。

 

SQL> selectcount(*) from sys.smon_scn_time; 

COUNT(*) 
---------- 
137545 
1 row selected.

--正常情况下,9i最多只能保存1440条记录。

 

SQL> select object_id from dba_objectswhere object_name = 'SMON_SCN_TIME'; 
OBJECT_ID 
---------- 
575 
1 row selected. 

SQL> select * fromv$locked_object where object_id = 575; 

XIDUSNXIDSLOT XIDSQN OBJECT_ID SESSION_ID 
---------- ---------- ---------- ---------- ---------- 
ORACLE_USERNAME OS_USER_NAME PROCESS 
------------------------------ ------------------------------ ------------ 
LOCKED_MODE 
----------- 
5 5 1494 575 164 
dbadmin 4444350 
3  <=Locked in row exclusive mode

 

 

4.1.2 处理方法

 

设置12500事件,停止SMON 进程更新SMON_SCN_TIME表,然后手工删除表中的记录。

 

SQL> alter system set events '12500 tracename context forever, level 10';

 

SQL> delete from smon_scn_time;

SQL> commit;

 

SQL> alter system set events '12500 tracename context off';

Now restart the instance.

 

 

4.2 Oracle 10g SMON_SCN_TIME 表频繁的被delete

 

High Executions Of Statement "deletefrom smon_scn_time..." [ID 375401.1]

 

4.2.1 现象

 

AWR报告显示smon_scn_time的删除操作频繁的被执行。

delete fromsmon_scn_time where thread=0 and time_mp = (select min(time_mp) fromsmon_scn_time where thread=0);

 

    导致这种现象的原因是SMON_SCN_TIME表和表上的索引不一致。需要重建SMON_SCN_TIME上的索引。

 

SQL> analyze table smon_scn_timevalidate structure cascade;
analyze table smon_scn_time validate structure cascade
*
ERROR at line 1 :
ORA-01499: table/Index Cross Reference Failure - see trace file

 

4.2.2 处理方法

 

connect / as sysdba
drop index smon_scn_time_scn_idx;
drop index smon_scn_time_tim_idx;
create unique index smon_scn_time_scn_idx on smon_scn_time(scn);
create unique index smon_scn_time_tim_idx on smon_scn_time(time_mp);
analyze table smon_scn_time validate structure cascade;

 



  由oradebug poke推进scn理解scn base及scn wrap系列一  

背景

   在v$transaction会看到scn,其中又分为scn base及scn wrap,这到底怎么回事呢?而且很多ORA报错与SCN有关,如果多了解一些SCN相关的知识,也便于我们
分析解决问题。   


结论

1,oradebug poke可以推进SCN,分为在数据库OPEN及MOUNT皆可以
oradebug setmypid


oradebug DUMPvar SGA kcsgscn_


oradebug poke 0x060012658 4 1000


2,关于kcsgscn_变量我是在BAIDU上面查的,而关于SCN到底是对应内存是哪块区域,我是采用多次运行oradebug DUMPvar SGA kcsgscn_,看哪些内存的值在变化,基本就是哪块


3,oradebug poke 0x060012658 4 1000 就是推进SCN的命令,具体含义如下:
  oradebug  poke 内存地址  长度  要修改的内容 ,注意这个要修改的内容必须是十进制,如果是16进制会报上述的错(这里我采用了反向对比思维),且这里长度是前4个字节


4,如果是在OPEN状态下推进SCN,oradebug DUMPvar SGA kcsgscn_是有值的,而在MOUNT因为数据库没有打开,所在是空的,全是0,那么如何调整SCN,可以基于每个文件头的BLOCK 1的数据结构kscnbas及kscnwrp进行调整
   这个数据结构对应select file#,name,checkpoint_change# from v$datafile;
  BBED> map
 File: /home/ora10g/asia/asia/users01.dbf (0)
 Block: 1                                     Dba:0x00000000
------------------------------------------------------------
 Data File Header


 struct kcvfh, 676 bytes                    @0       


 ub4 tailchk                                @8188    




BBED> p kcvfh
   struct kcvfhckp, 36 bytes                @484     
      struct kcvcpscn, 8 bytes              @484     
         ub4 kscnbas                        @484      0x028f5c58  --scn base  
         ub2 kscnwrp                        @488      0x0000      --scn wrap




5,select current_scn from v$database,这个SCN是一直在变化,可以叫作内存SCN


6,scn是由scn base及scn wrap构成的,当scn base达到一定程度,scn wrap则会递增,一般情况下scn wrap是0,不会变化


7,scn base及scn wrap也是数据块中的数据结构,可见scn base是4个字节,而scn wrap是2个字节
  也就是说scn base要用4个字节用完,scn wrap就会递增
  依理推理,4个字节为 power(2,32),也就是达到这个数据时,scn base就会归0,scn wrap递增1


8,基于  select file#,name,checkpoint_change# from v$datafile;和数据结构的scn base及scn wrap可知scn计算公式为


scn=scn wrap * power(2,32)+scn base


9,进一步引申,也可以计算出为scn最大值,因为scn base及scn wrap是由4个字节及4个字节构成的,而这些字节表示的数据范围是有限的
 


10,如果过小调整scn远小于checkpoint_change#,会引发ora-600 2662,当然解决也很容易,基于checkpoint_change#调大scn即可
   否则2662会引发数据库强制关闭


测试


SQL> select * from v$version where rownum=1;


BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bi


---可见事务也有scn base及scn wrap的概念
SQL> desc v$transaction;
 Name              Null?    Type
 ----------------- -------- ------------
 ADDR                       RAW(8)
 XIDUSN                     NUMBER
 XIDSLOT                    NUMBER
 XIDSQN                     NUMBER
 UBAFIL                     NUMBER
 UBABLK                     NUMBER
 UBASQN                     NUMBER
 UBAREC                     NUMBER
 STATUS                     VARCHAR2(16)
 START_TIME                 VARCHAR2(20)
 START_SCNB                 NUMBER  --scn base
 START_SCNW                 NUMBER  --scn wrap
 START_UEXT                 NUMBER
 START_UBAFIL               NUMBER
 START_UBABLK               NUMBER
 START_UBASQN               NUMBER
 START_UBAREC               NUMBER
 SES_ADDR                   RAW(8)
 FLAG                       NUMBER
 SPACE                      VARCHAR2(3)
 RECURSIVE                  VARCHAR2(3)
 NOUNDO                     VARCHAR2(3)
 PTX                        VARCHAR2(3)
 NAME                       VARCHAR2(256
                            )
 PRV_XIDUSN                 NUMBER
 PRV_XIDSLT                 NUMBER
 PRV_XIDSQN                 NUMBER
 PTX_XIDUSN                 NUMBER
 PTX_XIDSLT                 NUMBER
 PTX_XIDSQN                 NUMBER
 DSCN-B                     NUMBER --scn base
 DSCN-W                     NUMBER  --scn wrap
 USED_UBLK                  NUMBER
 USED_UREC                  NUMBER
 LOG_IO                     NUMBER
 PHY_IO                     NUMBER
 CR_GET                     NUMBER
 CR_CHANGE                  NUMBER
 START_DATE                 DATE
 DSCN_BASE                  NUMBER --scn base
 DSCN_WRAP                  NUMBER --scn wrap
 START_SCN                  NUMBER
 DEPENDENT_SCN              NUMBER
 XID                        RAW(8)
 PRV_XID                    RAW(8)
 PTX_XID                    RAW(8)




---普通数据块也有scn base及scn wrap的概念,且scn base为4个字节,scn wrap为2个字节
BBED> map
 File: /home/ora10g/asia/asia/users01.dbf (0)
 Block: 12                                    Dba:0x00000000
------------------------------------------------------------
 KTB Data Block (Table/Cluster)


 struct kcbh, 20 bytes                      @0       


 struct ktbbh, 72 bytes                     @20      


 struct kdbh, 14 bytes                      @100     


 struct kdbt[1], 4 bytes                    @114     


 sb2 kdbr[32]                               @118     


 ub1 freespace[7814]                        @182     


 ub1 rowdata[192]                           @7996    


 ub4 tailchk                                @8188    




BBED> p kcbh
struct kcbh, 20 bytes                       @0       
   ub1 type_kcbh                            @0        0x06
   ub1 frmt_kcbh                            @1        0xa2
   ub1 spare1_kcbh                          @2        0x00
   ub1 spare2_kcbh                          @3        0x00
   ub4 rdba_kcbh                            @4        0x0100000c
   ub4 bas_kcbh                             @8        0x00048e91  --scn base
   ub2 wrp_kcbh                             @12       0x0000  --scn wrap
   ub1 seq_kcbh                             @14       0x02
   ub1 flg_kcbh                             @15       0x06 (KCBHFDLC, KCBHFCKV)
   ub2 chkval_kcbh                          @16       0x7e45
   ub2 spare3_kcbh                          @18       0x0000


BBED> 


---数据文件头也有scn base及scn wrap的概念
BBED> map
 File: /home/ora10g/asia/asia/users01.dbf (0)
 Block: 1                                     Dba:0x00000000
------------------------------------------------------------
 Data File Header


 struct kcvfh, 676 bytes                    @0       


 ub4 tailchk                                @8188    




BBED> p kcvfh
struct kcvfh, 676 bytes                     @0       
   struct kcvfhbfh, 20 bytes                @0       
      ub1 type_kcbh                         @0        0x0b
      ub1 frmt_kcbh                         @1        0xa2
      ub1 spare1_kcbh                       @2        0x00
      ub1 spare2_kcbh                       @3        0x00
      ub4 rdba_kcbh                         @4        0x01000001
      ub4 bas_kcbh                          @8        0x00000000
      ub2 wrp_kcbh                          @12       0x0000




从上述我们发现基本scn wrap全是0,那么何时scn会变成非0呢,我想到了推进SCN,然后对比DUMP数据块,可以了其原理了




SQL> select current_scn,checkpoint_change# from v$database;


CURRENT_SCN CHECKPOINT_CHANGE#
----------- ------------------
     311981             296387




SQL> alter session set events 'immediate trace name adjust_scn level 1';


Session altered.


SQL> select current_scn,checkpoint_change# from v$database;


CURRENT_SCN CHECKPOINT_CHANGE#
----------- ------------------
     311996             296387




可见上述推进SCN太慢了
SQL> select 311996-311981 from dual;


311996-311981
-------------
           15          




---且ALERT会报权限不足的错误信息
Mon Nov 30 23:46:36 EST 2015
Errors in file /home/ora10g/admin/asia/udump/asia_ora_23849.trc:
ORA-01031: insufficient privileges


---上述推进SCN方法太慢,我们尝试另一种快速推进SCN的方法,不过要重启库到MOUNT状态
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount
ORACLE instance started.


Total System Global Area  901775360 bytes
Fixed Size                  2100424 bytes
Variable Size             226493240 bytes
Database Buffers          666894336 bytes
Redo Buffers                6287360 bytes
Database mounted.


---可见MOUNT状态下CURRENT_SCN为0,其它SCN列皆有值
SQL> select current_scn,checkpoint_change# from v$database;


CURRENT_SCN CHECKPOINT_CHANGE#
----------- ------------------
          0             312204






SQL> select file#,name,checkpoint_change# from v$datafile;


     FILE# NAME                                               CHECKPOINT_CHANGE#
---------- -------------------------------------------------- ------------------
         1 /home/ora10g/asia/asia/system01.dbf                            312204
         2 /home/ora10g/asia/asia/undotbs01.dbf                           312204
         3 /home/ora10g/asia/asia/sysaux01.dbf                            312204
         4 /home/ora10g/asia/asia/users01.dbf                             312204


SQL> select file#,checkpoint_change# from v$datafile_header;


     FILE# CHECKPOINT_CHANGE#
---------- ------------------
         1             312204
         2             312204
         3             312204
         4             312204




SQL> select to_char('312204','xxxxxxx') from dual;


TO_CHAR(
--------
   4c38c


---bbed查看数据文件的SCN,可知是4c38c


   struct kcvfhckp, 36 bytes                @484     
      struct kcvcpscn, 8 bytes              @484     
         ub4 kscnbas                        @484      0x0004c38c
         ub2 kscnwrp                        @488      0x0000


---用10015事件推进SCN发现没有变化,可见在MOUNT状态下不生效推进SCN
SQL> alter session set events '10015 trace name adjust_scn level 1';


Session altered.


SQL> select current_scn,checkpoint_change# from v$database;


CURRENT_SCN CHECKPOINT_CHANGE#
----------- ------------------
          0             312204


打开数据库看看有无生效,也是没有效果
SQL> alter database open;


Database altered.   




SQL> select current_scn,checkpoint_change# from v$database;


CURRENT_SCN CHECKPOINT_CHANGE#
----------- ------------------
     312409             312207


SQL> select file#,name,checkpoint_change# from v$datafile;


     FILE# NAME                                               CHECKPOINT_CHANGE#
---------- -------------------------------------------------- ------------------
         1 /home/ora10g/asia/asia/system01.dbf                            312207
         2 /home/ora10g/asia/asia/undotbs01.dbf                           312207
         3 /home/ora10g/asia/asia/sysaux01.dbf                            312207
         4 /home/ora10g/asia/asia/users01.dbf                             312207






---换另一种方法,用ORADEBUG POKE推进SCN
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount
ORACLE instance started.


Total System Global Area  901775360 bytes
Fixed Size                  2100424 bytes
Variable Size             226493240 bytes
Database Buffers          666894336 bytes
Redo Buffers                6287360 bytes
Database mounted.


SQL> oradebug setmypid
Statement processed.
SQL> oradebug DUMPvar SGA kcsgscn_
kcslf kcsgscn_ [060012658, 060012688) = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 60012338 00000000
SQL> 


SQL> select file#,name,checkpoint_change# from v$datafile;


     FILE# NAME                                               CHECKPOINT_CHANGE#
---------- -------------------------------------------------- ------------------
         1 /home/ora10g/asia/asia/system01.dbf                            312714
         2 /home/ora10g/asia/asia/undotbs01.dbf                           312714
         3 /home/ora10g/asia/asia/sysaux01.dbf                            312714
         4 /home/ora10g/asia/asia/users01.dbf                             312714


SQL> select to_char('312714','xxxxxx') from dual;


TO_CHAR
-------
  4c58a




  SQL> oradebug poke 0x060012658 8 0x0004c58a
BEFORE: [060012658, 060012660) = 00000000 00000000
AFTER:  [060012658, 060012660) = 0004C58A 00000000
SQL> oradebug DUMPvar SGA kcsgscn
kcslf kcsgscn_ [060012658, 060012688) = 0004C58A 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 60012338 00000000
SQL> 




SQL> alter database open;


Database altered.




SQL> select file#,name,checkpoint_change# from v$datafile;


     FILE# NAME                                               CHECKPOINT_CHANGE#
---------- -------------------------------------------------- ------------------
         1 /home/ora10g/asia/asia/system01.dbf                            312717
         2 /home/ora10g/asia/asia/undotbs01.dbf                           312717
         3 /home/ora10g/asia/asia/sysaux01.dbf                            312717
         4 /home/ora10g/asia/asia/users01.dbf                             312717


好像没起作用
SQL> select current_scn,checkpoint_change# from v$database;


CURRENT_SCN CHECKPOINT_CHANGE#
----------- ------------------
     312891             312717


---换个思路,试试在数据库打开时推进SCN
SQL> select file#,name,checkpoint_change# from v$datafile;


     FILE# NAME                                               CHECKPOINT_CHANGE#
---------- -------------------------------------------------- ------------------
         1 /home/ora10g/asia/asia/system01.dbf                            313429
         2 /home/ora10g/asia/asia/undotbs01.dbf                           313429
         3 /home/ora10g/asia/asia/sysaux01.dbf                            313429
         4 /home/ora10g/asia/asia/users01.dbf                             313429


SQL> select current_scn,checkpoint_change# from v$database;


CURRENT_SCN CHECKPOINT_CHANGE#
----------- ------------------
     313917             313429


SQL> select to_char('313917','xxxxxxxxxx') from dual;


TO_CHAR('31
-----------
      4ca3d


---经间隔多次运行如下ORADEBUG命令,我分析CURRENT_SCN就是内存中的第1部分(因为就这部分信息在变化,其它信息是固定的)
SQL> oradebug setmypid
Statement processed.
SQL> oradebug DUMPvar SGA kcsgscn_
kcslf kcsgscn_ [060012658, 060012688) = 0004CAD4 00000000 00000000 00000000 00000113 00000000 00000000 00000000 00000000 00000000 60012338 00000000
SQL> 
SQL> 
SQL> 
SQL> oradebug DUMPvar SGA kcsgscn_
kcslf kcsgscn_ [060012658, 060012688) = 0004CAD6 00000000 00000000 00000000 00000114 00000000 00000000 00000000 00000000 00000000 60012338 00000000
SQL> 
SQL> 
SQL> oradebug DUMPvar SGA kcsgscn_
kcslf kcsgscn_ [060012658, 060012688) = 0004CAD7 00000000 00000000 00000000 00000115 00000000 00000000 00000000 00000000 00000000 60012338 00000000
SQL>       


---所以我们只要改第1部分信息的内容即可
SQL> oradebug poke 0x060012658 4 FFFFA3523
ORA-01858: a non-numeric character was found where a numeric was expected
SQL> 


可见oradeug poke 的含义是oradebug  poke 内存地址  长度  要修改的内容 ,注意这个要修改的内容必须是十进制,如果是16进制会报上述的错(这里我采用了反向对比思维),且这里长度是前4个字节
SQL> oradebug poke 0x060012658 4 1000
BEFORE: [060012658, 06001265C) = 0004CB41
AFTER:  [060012658, 06001265C) = 000003E8
SQL> select to_number('3E8','xxxxxxxxx') from dual;


TO_NUMBER('3E8','XXXXXXXXX')
----------------------------
                        1000


---而且上述由于把SCN改得过小,小于数据文件及控制文件的SCN,会报ORA-600 的2662错误,处理很简单,快速基于checkpoint_change#把SCN变大即可,否则过会数据库就会DOWN机
SQL> select current_scn,checkpoint_change# from v$database;
select current_scn,checkpoint_change# from v$database
                                           *
ERROR at line 1:
ORA-00600: internal error code, arguments: [2662], [0], [71], [0], [333548],
[0], [], []


---基于上述分析,因为原来SCN是313917,我们加到19999999999


SQL> oradebug setmypid
Statement processed.
SQL> select power(2,32) from dual;


POWER(2,32)
-----------
 4294967296


如果把SCN调整为上述的值,马上ALAERT会报错
SQL> oradebug DUMPvar SGA kcsgscn_
kcslf kcsgscn_ [060012658, 060012688) = 000565AE 00000000 00000000 00000000 00000075 00000000 00000000 00000000 00000000 00000000 60012338 00000000
SQL> oradebug poke 0x060012658 4 4294967296
BEFORE: [060012658, 06001265C) = 000565B3
AFTER:  [060012658, 06001265C) = 00000000


Tue Dec 01 01:27:33 EST 2015
Errors in file /home/ora10g/admin/asia/bdump/asia_cjq0_27711.trc:
ORA-00604: error occurred at recursive SQL level 1
ORA-08176: consistent read failure; rollback data not available


--所以可见SCN也不能随意去调太大,ORACLE内部肯定有个控制算法的,否则会把库搞DOWN掉
SQL> oradebug poke 0x060012658 4 42949670
BEFORE: [060012658, 06001265C) = 00000003
AFTER:  [060012658, 06001265C) = 028F5C26






SQL> alter system checkpoint;


System altered.


SQL> alter system checkpoint;


System altered.


SQL> select file#,name,checkpoint_change# from v$datafile;


     FILE# NAME                                               CHECKPOINT_CHANGE#
---------- -------------------------------------------------- ------------------
         1 /home/ora10g/asia/asia/system01.dbf                          42949720
         2 /home/ora10g/asia/asia/undotbs01.dbf                         42949720
         3 /home/ora10g/asia/asia/sysaux01.dbf                          42949720
         4 /home/ora10g/asia/asia/users01.dbf                           42949720


---可见SCN已经调整为指定的SCN了
SQL> select current_scn,checkpoint_change# from v$database;


CURRENT_SCN CHECKPOINT_CHANGE#
----------- ------------------
   42949724           42949720






---换个思路继糿研究SCN BASE及SCN WRAP,如果我一直增加SCN BASE,SCN WRAP会有变化呢,我理解肯定是SCN BASE大到一定程度,SCN WRAP就会有变化
BBED> map
 File: /home/ora10g/asia/asia/users01.dbf (0)
 Block: 1                                     Dba:0x00000000
------------------------------------------------------------
 Data File Header


 struct kcvfh, 676 bytes                    @0       


 ub4 tailchk                                @8188    




BBED> p kcvfh
   struct kcvfhckp, 36 bytes                @484     
      struct kcvcpscn, 8 bytes              @484     
         ub4 kscnbas                        @484      0x028f5c58  --scn base
         ub2 kscnwrp                        @488      0x0000






SQL> select to_number('&x','xxxxxxxx') from dual;
Enter value for x: 28f5c58
old   1: select to_number('&x','xxxxxxxx') from dual
new   1: select to_number('28f5c58','xxxxxxxx') from dual


TO_NUMBER('28F5C58','XXXXXXXX')
-------------------------------
                       42949720




BBED> set offset 484
        OFFSET          484


BBED> dump count 5
 File: /home/ora10g/asia/asia/users01.dbf (0)
 Block: 1                Offsets:  484 to  488           Dba:0x00000000
------------------------------------------------------------------------
 585c8f02 00 


 <32 bytes="" per="" line="">


 SQL> select power(2,31) from dual;


POWER(2,31)
-----------
 2147483648


 SQL> select to_char('2147483648','xxxxxxxxx') from dual;


TO_CHAR('2
----------
  80000000


BBED> modify /x 00000080
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) Y
 File: /home/ora10g/asia/asia/users01.dbf (0)
 Block: 1                Offsets:  484 to  488           Dba:0x00000000
------------------------------------------------------------------------
 00000080 00 


 <32 bytes="" per="" line="">




--还要调整tailchk
可以看到tailchk校验由ub4 bas_kcbh的低4位+ub1 type_kcbh+ub1 seq_kcbh


BBED> p tailchk
ub4 tailchk                                 @8188     0x00000b01


      ub4 bas_kcbh                          @8        0x00000000


      ub1 type_kcbh                         @0        0x0b


      ub1 seq_kcbh                          @14       0x01




BBED> sum apply
Check value for File 0, Block 1:
current = 0x2dac, required = 0x2dac


   ---调整后   
   struct kcvfhckp, 36 bytes                @484     
      struct kcvcpscn, 8 bytes              @484     
         ub4 kscnbas                        @484      0x80000000
         ub2 kscnwrp                        @488      0x0000




BBED> p tailchk
ub4 tailchk                                 @8188     0x00000b01




SQL> conn scott/system
Connected.
SQL> create table t_modafter(a int);


Table created.


SQL> insert into t_modafter values(1);


1 row created.


SQL> commit;


Commit complete.




SQL> conn /as sysdba
Connected.
SQL> alter system checkpoint;


System altered.


SQL> alter system flush buffer_cache;


System altered.


---调整scn base到最大值-1
SQL> select power(2,32)-1 from dual;


POWER(2,32)-1
-------------
   4294967295


SQL> select to_char('4294967295','xxxxxxxxxx') from dual;


TO_CHAR('42
-----------
   ffffffff


---报错可以分2步进行,即先2个字节进行,然后再把余下的2个字节修改完
BBED> modify /x ffffffff
BBED-00209: invalid number (ffffffff)


BBED> modify /x ffff
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) Y
 File: /home/ora10g/asia/asia/users01.dbf (0)
 Block: 1                Offsets:  484 to  488           Dba:0x00000000
------------------------------------------------------------------------
 ffff0080 00 


 <32 bytes="" per="" line="">




 BBED> set offset 486
        OFFSET          486


BBED> dump
 File: /home/ora10g/asia/asia/users01.dbf (0)
 Block: 1                Offsets:  486 to  488           Dba:0x00000000
------------------------------------------------------------------------
 008000 


 <32 bytes="" per="" line="">


BBED> modify /x ffff
 File: /home/ora10g/asia/asia/users01.dbf (0)
 Block: 1                Offsets:  486 to  488           Dba:0x00000000
------------------------------------------------------------------------
 ffff00 


 <32 bytes="" per="" line="">




BBED> dump
 File: /home/ora10g/asia/asia/users01.dbf (0)
 Block: 1                Offsets:  484 to  486           Dba:0x00000000
------------------------------------------------------------------------
 ffffff 


 <32 bytes="" per="" line="">


BBED> p kcvfh
   struct kcvfhckp, 36 bytes                @484     
      struct kcvcpscn, 8 bytes              @484     
         ub4 kscnbas                        @484      0xffffffff  scn_base已经调整为 power(2,32)-1 ,其中32代表4个字节,每个字节byte即8bit,所以就是32个bit,可以表示的数据即power(2,32)
         ub2 kscnwrp                        @488      0x0000


SQL> alter system flush buffer_cache;


System altered.


SQL> alter system checkpoint;
System altered.


BBED> p kcvfh


   struct kcvfhckp, 36 bytes                @484     
      struct kcvcpscn, 8 bytes              @484     
         ub4 kscnbas                        @484      0x00000002
         ub2 kscnwrp                        @488      0x0001  ---看到没,SCN WRAP有值了,哈哈说明,SCN BASE大到一定程度,它就有值了




SQL> select file#,name,checkpoint_change# from v$datafile;


     FILE# NAME                                               CHECKPOINT_CHANGE#
---------- -------------------------------------------------- ------------------
         1 /home/ora10g/asia/asia/system01.dbf                        4294967298
         2 /home/ora10g/asia/asia/undotbs01.dbf                       4294967298
         3 /home/ora10g/asia/asia/sysaux01.dbf                        4294967298
         4 /home/ora10g/asia/asia/users01.dbf                         4294967298   




可见scn=scn wrap * power(2,32)+scn base
SQL> select 1*4294967296+2 from dual;


1*4294967296+2
--------------
    4294967298


也就是说scn wrap有值时,scn又开始从0开始计数,由此可见ORACLE设计的精妙所在,再深入一些,也可以知道SCN最大值是什么,哈哈


了解你所不知道的SMON功能(十):维护SMON_SCN_TIME字典基表







 
  





>>&>>>>



                                                                                                        












 
  




>





 
  



>>>>>


     


4ae5000451629b27ddae

4ae5000451629b27ddae

&

4ae5000451629b27ddae

 

4aeb00019ff180008e93

4ae90001a0decda8c794

4aeb00019ff2614af94c

&

    

4ae90001a0dc7b237d39




   


4ae70004bf22b4b2c44b

4ae90001a241a7cc0a58

4ae70004bf2120492fd3

4ae70004bf20d5105272

4aeb0001a17351abbc99


  •  








4ae90001a2421de65ab4

4aec00014c2ad66521f0

4aeb0001a174be4b2f66

4ae5000452c8c19d0cff

4aed000129e4f684aa72










&

          

img_e3029f287d989cd04bd75432ecc1c172.png
DBA笔试面试讲解群
《DBA宝典》读者群 欢迎与我联系



相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
13天前
|
存储 SQL Oracle
【Oracle】玩转Oracle数据库(二):体系结构、存储结构与各类参数
【Oracle】玩转Oracle数据库(二):体系结构、存储结构与各类参数
35 7
|
1月前
|
存储 SQL Oracle
Oracle系列十九:Oracle的体系结构
Oracle系列十九:Oracle的体系结构
|
1月前
|
SQL 存储 移动开发
[Oracle]知识点
本篇文章是关于Oracle各类知识点的小结,例如:rownum、约束、内置函数等。 如果文中阐述不全或不对的,多多交流。
61 4
[Oracle]知识点
|
7月前
|
存储 SQL Oracle
oracle知识点总结
oracle数据可系统是美国oracle(甲骨文)公司提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器或B/S体系结构的数据库之一,oracle数据库时目前世界上使用最为广泛的数据库管理系统,作为一个通用的数据库系统,它具有完善的数据库管理功能,是关系型数据库,比mysql更为庞大,在现行的关系型数据库中排名第一(oracle、mysql、SqlServer),时间是最为精确的。
54 0
|
存储 SQL 运维
Oracle数据库系统管理与运维 | Oracle体系结构与性能优化
Oracle数据库系统管理与运维 | Oracle体系结构与性能优化
184 0
Oracle数据库系统管理与运维 | Oracle体系结构与性能优化
|
Oracle 关系型数据库 数据库
|
SQL 存储 Oracle
不得不会的Oracle数据库知识点(四)
不得不会的Oracle数据库知识点(四)
|
SQL Oracle 关系型数据库
不得不会的Oracle数据库知识点(三)
不得不会的Oracle数据库知识点(三)
|
SQL 存储 Oracle
不得不会的Oracle数据库知识点(二)
不得不会的Oracle数据库知识点(二)
|
Oracle 关系型数据库 数据库
不得不会的Oracle数据库知识点(一)
不得不会的Oracle数据库知识点(一)

推荐镜像

更多