当前位置:  数据库>oracle

使用Oradebug修改Oracle SCN

    来源: 互联网  发布时间:2017-06-24

    本文导语: Oracle SCN对于数据库运行、维护而言是至关重要的因素。在启动从mount到open过程中,主要是各种文件的SCN进行比较的行为。通常情况下,我们是不需要介入到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

此时,关闭重启系统也不会有问题。篇幅原因,不进行具体展示。那么,很多时候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,是我们在故障修复时候非常快捷的方法。不过,快捷建立在对内部机制清晰理解的前提之下。所以,无论何种场景进行修复,有备份、可恢复是我们工作的基本前提。


    
 
 

您可能感兴趣的文章:

  • linux/Centos/ubuntu下如何使用umask命令修改新建文件时的默认权限
  • 使用SSH修改linux密码的问题
  • 如何在使用命令行去修改系统脚本?
  • 关于使用SHELL修改文件的
  • 大家修改内核时使用哪个编辑器?
  • 请问如何在一个文件系统修改源码管理并使用多个卷(存储设备)
  • ORACEL使用脚本来修改表结构
  • ORACLE 修改表结构 之ALTER CONSTAINTS的使用
  • 请问如何使用系统命令修改系统参数
  • 有没有方法可以使用脚本批量修改bash环境变量
  • 如何修改tomcat.sh文件,限定java使用的内存?????
  • java的应用程序中如何定义一个全局变量,在程序的任何地方都可以修改使用?
  • 使用usermod -u 来修改用户主目录和默认shell时提示找不到这个用户
  • 使用phpMyAdmin修改MySQL数据库root用户密码的方法
  • 使用jQuery的attr方法来修改onclick值
  • 使用tomcat4.0.3,当服务器启动装载servlet后,如果servlet有些修改,是否需要重新启动tomcat?
  • 请问如何使用snmp给一个表添加、修改记录?
  • MYSQL使用inner join 进行 查询/删除/修改示例
  • 使用linq to xml修改app.config示例(linq读取xml)
  • C#使用非托管代码直接修改字符串的方法
  • 新手请教一个关于使用String类修改的简单问题。谢谢
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • linux下安装oracle后使用命令行启动的方法 linux启动oracle
  • Oracle9i 9.0.1的JDBC Drivers 可以给Oracle 8.0.5使用马?
  • Suse linux使用oracle问题
  • 请问:在使用oracle数据库作开发时,是使用pro*c作开发好些,还是使用库函数如oci等好一些啊?或者它们有什么区别或者优缺点啊?
  • jbuilder中使用oracle的问题
  • 求redhat linux 9.0下可以使用的oracle 10g或9i,还有redhat linux 9.0下可以使用的eclipse下载地址
  • Oracle事务!使用游标提交过程
  • 在Jbuilder7下,使用DbPilot.exe连接oracle,报错!请教高手!
  • AIX 64位系统上如何使用32位OCI oracle driver
  • Oracle中SQL语句连接字符串的符号使用介绍
  • 使用X manager连接oracle数据库的步骤
  • C++使用OCCI连Oracle10g的错误
  • 使用工具 plsqldev将Excel导入Oracle数据库
  • Linux下Oracle的sqlplus使用光标上下左右方法
  • Oracle 数据 使用游标
  • oracle使用sql脚本生成csv文件案例学习
  • Linux中Oracle使用相关知识集锦
  • Oracle密码文件的使用和维护第1/3页
  • Oracle 触发器的使用小结
  • Oracle SQL使用时注意自己的输入
  • C++ I/O 成员 tellg():使用输入流读取流指针
  • 在测试memset函数的执行效率时,分为使用Cash和不使用Cash辆种方式,该如何控制是否使用缓存?
  • C++ I/O 成员 tellp():使用输出流读取流指针
  • 求ibm6000的中文使用手册 !从来没用过服务器,现在急需使用它,不知如何使用! 急!!!!!
  • Python不使用print而直接输出二进制字符串
  • 急求结果!!假设一个有两个元素的信号量集S,表示了一个磁带驱动器系统,其中进程1使用磁带机A,进程2同时使用磁带机A和B,进程3使用磁带机B。
  • Office 2010 Module模式下使用VBA Addressof
  • c#中SAPI使用总结——SpVoice的使用方法
  • windows下tinyxml.dll下载安装使用(c++解析XML库)
  • 使用了QWidget的程序,如何使用后台程序启动它?
  • tcmalloc内存泄露优化c++开源库下载,安装及使用介绍


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3