阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

使用Oradebug修改Oracle SCN

169次阅读
没有评论

共计 7030 个字符,预计需要花费 18 分钟才能阅读完成。

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

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

3、Mount 状态修改 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,包括 base 和 wrap 两部分。我们这次修改 wrap 从 0 到 1。这个过程中,我们需要写入 base 和 wrap 两个部分,如果我们只写入了 wrap 部分,base 部分保持 0,那么系统运行的时候,会从 base 为 0 开始。

此时,需要查看一下当前文件里面 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。下面分别写入 base 和 wrap 取值。

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 相关信息见 Oracle 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=12

本文永久更新链接地址 :http://www.linuxidc.com/Linux/2016-10/136567.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计7030字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中