使用Oradebug修改Oracle SCN

Oracle SCN对于数据库运行、维护而言是至关重要的因素。在启动从mount到open过程中,主要是各种文件的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

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

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

2、Open状态下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近似SCN的Base部分。注意: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进制。

每一个取值段,用8个16进制对应,对应到数字位数是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

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/349d57d27b40809382198543b00a04e5.html