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

Oracle丢失的是所有的redo日志组

121次阅读
没有评论

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

假设 Oracle 丢失的是所有的 redo 日志组,分下列几种情况分别处理:

  1. Oracle 没开归档,一致性关闭数据库
  2. Oracle 没开归档,非一致性关闭数据库
  3. Oracle 开归档,一致性关闭数据库
  4. Oracle 开归档,非一致性关闭数据库

一:Oracle 没开归档,一致性关闭数据库

我做实验的过程中有一个诡异的情况,我先把 redo 文件从操作系统层面都删除了,但是数据库正常创建表,insert 数据,我理解的是当你 commit 的时候,会触发 lgwr 进程从 redo log buffer 中涮新 redo 到 redo 文件中,但是 redo 文件已经被删除了,就会报错,但是他并没有报错:

[root@testdb59 /data/u01/app/oracle/oradata/stdb59]# ll

total 13697796

-rw-r—– 1 oracle oinstall 144916480 Apr 5 22:30 control01.ctl

-rw-r—– 1 oracle oinstall 2147491840 Apr 5 22:26 liuwenhe.dbf

-rw-r—– 1 oracle oinstall 52429312 Apr 5 22:26 redo01.log

-rw-r—– 1 oracle oinstall 52429312 Apr 5 22:29 redo03.log

-rw-r—– 1 oracle oinstall 4938801152 Apr 5 22:26 soe3.dbf

-rw-r—– 1 oracle oinstall 2469404672 Apr 5 22:26 soe.dbf

-rw-r—– 1 oracle oinstall 2705334272 Apr 5 22:26 sysaux01.dbf

-rw-r—– 1 oracle oinstall 786440192 Apr 5 22:26 system01.dbf

-rw-r—– 1 oracle oinstall 30416896 Oct 16 12:37 temp01.dbf

-rw-r—– 1 oracle oinstall 1073750016 Apr 5 22:26 temp.dbf

-rw-r—– 1 oracle oinstall 309338112 Apr 5 22:26 undotbs01.dbf

-rw-r—– 1 oracle oinstall 166469632 Apr 5 22:26 users01.dbf

删除 redo 文件

[root@testdb59 /data/u01/app/oracle/oradata/stdb59]# rm *.log

再次查看,发现确实已经没有了 redo 文件

[root@testdb59 /data/u01/app/oracle/oradata/stdb59]# ll

total 13595388

-rw-r—– 1 oracle oinstall 144916480 Apr 5 22:50 control01.ctl

-rw-r—– 1 oracle oinstall 2147491840 Apr 5 22:50 liuwenhe.dbf

-rw-r—– 1 oracle oinstall 4938801152 Apr 5 22:50 soe3.dbf

-rw-r—– 1 oracle oinstall 2469404672 Apr 5 22:50 soe.dbf

-rw-r—– 1 oracle oinstall 2705334272 Apr 5 22:50 sysaux01.dbf

-rw-r—– 1 oracle oinstall 786440192 Apr 5 22:50 system01.dbf

-rw-r—– 1 oracle oinstall 30416896 Oct 16 12:37 temp01.dbf

-rw-r—– 1 oracle oinstall 1073750016 Apr 5 22:41 temp.dbf

-rw-r—– 1 oracle oinstall 309338112 Apr 5 22:50 undotbs01.dbf

-rw-r—– 1 oracle oinstall 166469632 Apr 5 22:50 users01.dbf

SQL> create table t(int int);

Table created.

SQL> insert into t values (100);

1 row created.

SQL> commit;

SQL>alter system switch logfile;

System altered.

SQL> alter system checkpoint;

System altered.

有点理解不了!!!! 问了下老师,才知道原来是打开的文件句柄还在,重启之后就没有了! 就会报错

(体外话:也就是说 rm 这个文件了,但是这个文件实际上还是存在的,先说一下他的工作原理吧,然后我在把试验分享给大家,工作原理其实也不难,这个工具需要在 ext3 或者 ext4 的文件系统上才可以实现,因为 ext3 文件系统是日志型文件系统,ext3 文件系统储存信息的时候是由 inode 号和 block 块存储的。

神马? 不知道什么是 inode 号? 和 block 块? 好吧,在说明白点,比如:一个分区比如一本书,那么 block 块就是书每页的内容,而 inode 号 就是书的目录,系统找文件的时候先找 inode 号 然后根据 inode 号去找硬盘上的 block 快信息,明白了吧!

在说一下删除的原理吧。当硬盘上的一个文件删除,其实没有真正想象中的那样在硬盘上清除掉的,他是把 inode 号和 block 块的那个链子 断开,但是真正的数据还是在硬盘上的,有没有感觉在 windos 上删除是那么快,没考虑到这吧,当你在删除文件的地方重新复制了新文件,那时候才会把之前的文件覆盖掉,也就是说删除了没有关系,千万不要往那个位置放文件了 )

因为数据库是一致性关闭的,也就是不需要实例恢复,也就不需要丢失的 redo,所以可以直接删除重建,当然也可以 recover database 来恢复丢失的 redo, 所以针对这种情况,有两种恢复方式:

方法一:直接 clear 相应的 redo 日志组! 也就是删除重新建立!

SQL> shutdown immediate #一致性关闭

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL> startup mount

ORACLE instance started.

Total System Global Area 1603411968 bytes

Fixed Size 2253664 bytes

Variable Size 1275071648 bytes

Database Buffers 318767104 bytes

Redo Buffers 7319552 bytes

Database mounted.

SQL> archive log list;

Database log mode No Archive Mode

Automatic archival Disabled

Archive destination USE_DB_RECOVERY_FILE_DEST

Oldest online log sequence 30641

Current log sequence 30642

清理删除从新建立或者直接 clear 所有的 redo 日志组,包括当前状态的和 active 状态的 redo 日志组!

SQL> alter database clear logfile group 1;

Database altered.

SQL> alter database clear logfile group 3;

Database altered.

SQL> alter database open ;

Database altered.

方法二:recover 的方式恢复重做日志,我的实验过程中,有的时候这个方法会报错,如果报错那么就使用第一种方式恢复!

SQL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL> startup mount

ORACLE instance started.

Total System Global Area 830930944 bytes

Fixed Size 2257800 bytes

Variable Size 536874104 bytes

Database Buffers 289406976 bytes

Redo Buffers 2392064 bytes

Database mounted.

SQL>

### 恢复丢失的 redo 文件,但是需要 open resetlogs 之后才能自动创建上!

SQL> recover database until cancel;

Media recovery complete.

SQL> alter database open resetlogs;

Database altered.

二:Oracle 没开归档,非一致性关闭数据库

[root@testdb59 /data/u01/app/oracle/oradata/stdb59]# rm -f *.log

SQL> shu abort ### 非一致性关闭数据库

ORACLE instance shut down.

这个时候尝试使用前面的 clear 或者 recover database 都会报错,无法恢复,因为这个时候是需要做实例恢复的,那么什么时候需要实例恢复的判断依据,请参考另一篇文章 (Oracle 原理 —– 关于 oracle 实例恢复的前滚和回滚的理解),报错如下:

首先尝试重建,当你尝试 clear 当前的日志组的时候,会报错提示是需要的!!! 因为非一致性关闭确实需要使用丢失的 active 和 current 状态的 redo 来实例恢复!

首先启动数据库到 mount 状态

SQL> alter database clear logfile group 3;

alter database clear logfile group 3

*

ERROR at line 1:

ORA-01624: log 3 needed for crash recovery of instance stdb59 (thread 1)

ORA-00312: online log 3 thread 1:

‘/data/u01/app/oracle/oradata/stdb59/redo03.log’

然后尝试 recover database, 结果肯定不可以,因为实例恢复需要的 redo 已经丢失!!

SQL> recover database until cancel;

ORA-00279: change 21959466 generated at 04/06/2019 21:15:45 needed for thread 1

ORA-00289: suggestion :

/data/u01/app/oracle/fast_recovery_area/STDB59/archivelog/2019_04_06/o1_mf_1_2_%

u_.arc

ORA-00280: change 21959466 for thread 1 is in sequence #2

Specify log: {<RET>=suggested | filename | AUTO | CANCEL}

CANCEL

ORA-01547: warning: RECOVER succeeded but OPEN RESETLOGS would get error below

ORA-01194: file 1 needs more recovery to be consistent

ORA-01110: data file 1: ‘/data/u01/app/oracle/oradata/stdb59/system01.dbf’

ORA-01112: media recovery not started

SQL> alter database open RESETLOGS;

alter database open RESETLOGS

ERROR at line 1:

ORA-01194: file 1 needs more recovery to be consistent

ORA-01110: data file 1: ‘/data/u01/app/oracle/oradata/stdb59/system01.dbf’

那么针对这种情况,恢复的方式如下:

使用一个隐含参数_allow_resetlogs_corruption 强制启动数据库,设置此参数之后,在数据库 Open 过程中,Oracle 会跳过某些一致性检查,从而使数据库可能跳过不一致状态,到达 open 数据库的目的

SQL> create pfile=’/home/oracle/pfile.ora’ from spfile;

File created.

然后在 /home/oracle/pfile.ora 添加上

*._allow_resetlogs_corruption=true

SQL> startup mount pfile=’/home/oracle/pfile.ora’;

SQL> recover database until cancel; #恢复丢失的 redo 文件

ORA-00279: change 21959471 generated at 04/06/2019 22:34:01 needed for thread 1

ORA-00289: suggestion :

/data/u01/app/oracle/fast_recovery_area/STDB59/archivelog/2019_04_06/o1_mf_1_2_%

u_.arc

ORA-00280: change 21959471 for thread 1 is in sequence #2

Specify log: {<RET>=suggested | filename | AUTO | CANCEL}

CANCEL

ORA-01547: warning: RECOVER succeeded but OPEN RESETLOGS would get error below

ORA-01194: file 1 needs more recovery to be consistent

ORA-01110: data file 1: ‘/data/u01/app/oracle/oradata/stdb59/system01.dbf’

ORA-01112: media recovery not started

幸运的话就可以直接以 resetlogs 方式 open 数据库了!

SQL> alter database open RESETLOGS;

Database altered.

如果遇到下面的错误,那么你就得重建控制文件了:

SQL> alter database open RESETLOGS;

alter database open RESETLOGS

*

ERROR at line 1:

ORA-01092: ORACLE instance terminated. Disconnection forced

ORA-00704: bootstrap process failure

ORA-00704: bootstrap process failure

ORA-00600: internal error code, arguments: [2662], [0], [21959484], [0],

[21959877], [4194545], [], [], [], [], [], []

Process ID: 13177

Session ID: 63 Serial number: 5

重建数据库控制文件

1) 直接使用如下 alter database backup controlfile 这种会报错

SQL> alter database backup controlfile to trace as ‘/data/u01/control_rebuild.trc’;

alter database backup controlfile to trace as ‘/data/u01/control_rebuild.trc’

*

ERROR at line 1:

ORA-16433: The database must be opened in read/write mode.

2) 还可以使用如下特定的格式来重建,

查询数据库的 redo 信息:

SQL> select GROUP#,MEMBER from v$logfile;

GROUP# MEMBER

3 /data/u01/app/oracle/oradata/stdb59/redo03.log

1 /data/u01/app/oracle/oradata/stdb59/redo01.log

查询数据库的 datafile 信息

SQL> select MEMBER from v$logfile;

MEMBER

——————————————————————————–

/data/u01/app/oracle/oradata/stdb59/redo03.log

/data/u01/app/oracle/oradata/stdb59/redo01.log

/data/u01/app/oracle/oradata/stdb59/redo04.log

/data/u01/app/oracle/oradata/stdb59/redo05.log

/data/u01/app/oracle/oradata/stdb59/redo06.log

/data/u01/app/oracle/oradata/stdb59/redo07.log

查出数据库字符集:

SQL> select userenv(‘language’) nls_lang from dual;

NLS_LANG

—————————————————-

AMERICAN_AMERICA.AL32UTF8

然后编辑出创建控制文件的脚本:注意这里的的 testdb57 为数据库 (db_name), 如果是 adg 转换成的主库,不要写 db_unique_name

CREATE CONTROLFILE REUSE DATABASE ‘testdb57’ NORESETLOGS ARCHIVELOG

MAXLOGFILES 50

MAXLOGMEMBERS 5

MAXDATAFILES 100

MAXINSTANCES 8

MAXLOGHISTORY 226

LOGFILE

GROUP 3 ‘/data/u01/app/oracle/oradata/stdb59/redo03.log’ SIZE 50M,

GROUP 1 ‘/data/u01/app/oracle/oradata/stdb59/redo01.log’ SIZE 50M

DATAFILE

‘/data/u01/app/oracle/oradata/stdb59/system01.dbf’,

‘/data/u01/app/oracle/oradata/stdb59/sysaux01.dbf’,

‘/data/u01/app/oracle/oradata/stdb59/undotbs01.dbf’,

‘/data/u01/app/oracle/oradata/stdb59/users01.dbf’,

‘/data/u01/app/oracle/oradata/stdb59/liuwenhe.dbf’,

‘/data/u01/app/oracle/oradata/stdb59/soe.dbf’,

‘/data/u01/app/oracle/oradata/stdb59/soe3.dbf’

CHARACTER SET AL32UTF8;

然后直接将数据库启动到 nomount 状态,执行创建脚本即可

SQL> startup nomount pfile=’/home/oracle/pfile.ora’;

ORACLE instance started.

Total System Global Area 1603411968 bytes

Fixed Size 2253664 bytes

Variable Size 1275071648 bytes

Database Buffers 318767104 bytes

Redo Buffers 7319552 bytes

CREATE CONTROLFILE REUSE DATABASE ‘testdb57’ NORESETLOGS ARCHIVELOG

MAXLOGFILES 50

MAXLOGMEMBERS 5

MAXDATAFILES 100

MAXINSTANCES 8

MAXLOGHISTORY 226

LOGFILE

GROUP 3 ‘/data/u01/app/oracle/oradata/stdb59/redo03.log’ SIZE 50M,

GROUP 1 ‘/data/u01/app/oracle/oradata/stdb59/redo01.log’ SIZE 50M

DATAFILE

‘/data/u01/app/oracle/oradata/stdb59/system01.dbf’,

‘/data/u01/app/oracle/oradata/stdb59/sysaux01.dbf’,

‘/data/u01/app/oracle/oradata/stdb59/undotbs01.dbf’,

‘/data/u01/app/oracle/oradata/stdb59/users01.dbf’,

‘/data/u01/app/oracle/oradata/stdb59/liuwenhe.dbf’,

‘/data/u01/app/oracle/oradata/stdb59/soe.dbf’,

‘/data/u01/app/oracle/oradata/stdb59/soe3.dbf’

CHARACTER SET AL32UTF8;

Control file created.

然后使用 oradebug 推进内存中 scn 号, 以便于执行后面的 recover 来恢复丢失的 redo 文件,因为 recover 的过程会读取内存中 scn。注意 alter session set events ‘10015 trace name adjust_scn level 10’; 这种方式在 11.2.0.4 已经失效了

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

SQL> oradebug poke 0x06001AE70 4 0x001B7740

oradebug 推进 scn 号,poke 命令中,第一位参数是对应写入的内存位数,第二位参数是写入长度,第三位参数是写入取值。默认写入取值是 10 进制,我们在这里指定写入 16 进制 (0x 开头),每一个取值段,用 8 个 16 进制对应,对应到数字位数是 4 位

首先查出数据库的控制文件中的 scn 号

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

FILE# CHECKPOINT_CHANGE#

———- ——————

1 21959486

2 21959486

3 21959486

4 21959486

5 21959486

6 21959486

7 21959486

7 rows selected.

SQL> oradebug setmypid

Statement processed.

SQL> oradebug DUMPvar SGA kcsgscn_

kcslf kcsgscn_ [06001AE70, 06001AEA0) = 014F14A2 00000001 00000000 00000000 000000EB 00000000 00000000 00000000 00000000 00000000 6001AB50 00000000

SQL> oradebug poke 0x06001AE70 4 21959486

BEFORE: [06001AE70, 06001AE74) = 00000000

AFTER: [06001AE70, 06001AE74) = 014F133E

(或者可以把 21959486 转换成 16 进制,然后再修改

SQL> select to_char(21959486, ‘XXXXXXXXXXX’) from dual;

TO_CHAR(2195

————

14F133E

SQL> oradebug poke 0x06001AE70 4 0x14F133E

BEFORE: [06001AE70, 06001AE74) = 00000000

AFTER: [06001AE70, 06001AE74) = 014F133E)

再次查看确实已经变成了 014F133E(对应 10 进制是 21959486)

SQL> oradebug DUMPvar SGA kcsgscn_

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

然后执行 recover 进行不完全恢复:

SQL> recover database until cancel;

ORA-00279: change 21959486 generated at 04/06/2019 23:52:28 needed for thread 1

ORA-00289: suggestion :

/data/u01/app/oracle/fast_recovery_area/STDB59/archivelog/2019_04_07/o1_mf_1_2_%

u_.arc

ORA-00280: change 21959486 for thread 1 is in sequence #2

Specify log: {<RET>=suggested | filename | AUTO | CANCEL}

CANCEL

ORA-01547: warning: RECOVER succeeded but OPEN RESETLOGS would get error below

ORA-01194: file 1 needs more recovery to be consistent

ORA-01110: data file 1: ‘/data/u01/app/oracle/oradata/stdb59/system01.dbf’

ORA-01112: media recovery not started

SQL> alter database open resetlogs;

Database altered.

至此恢复成功!

三:oracle 开归档,一致性关闭

这种情况是同情况 1,不需要做实例恢复,所以可以直接删除从新或者 recover 所有的 redo 组即可,

方法一:直接 clear 相应的 redo 日志组! 也就是删除重新建立!

SQL> shutdown immediate #一致性关闭

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL> startup mount

ORACLE instance started.

Total System Global Area 1603411968 bytes

Fixed Size 2253664 bytes

Variable Size 1275071648 bytes

Database Buffers 318767104 bytes

Redo Buffers 7319552 bytes

Database mounted.

清理删除从新建立或者直接 clear 所有的 redo 日志组,包括当前状态的和 active 状态的 redo 日志组!

SQL> alter database clear logfile group 1;

Database altered.

SQL> alter database clear logfile group 3;

Database altered.

SQL> alter database open ;

Database altered.

方法二:recover 的方式恢复重做日志,我的实验过程中,有的时候这个方法会报错,如果报错那么就使用第一种方式恢复!

SQL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL> startup mount

ORACLE instance started.

Total System Global Area 830930944 bytes

Fixed Size 2257800 bytes

Variable Size 536874104 bytes

Database Buffers 289406976 bytes

Redo Buffers 2392064 bytes

Database mounted.

SQL>

### 恢复丢失的 redo 文件,但是需要 open resetlogs 之后才能自动创建上!

SQL> recover database until cancel;

Media recovery complete.

SQL> alter database open resetlogs;

Database altered.

四:开归档,非一致性关闭;

这种情况,只能借助归档日志做不完全恢复!

SQL> select * from v$log;

GROUP# THREAD# SEQUENCE# BYTES BLOCKSIZE MEMBERS ARC

———- ———- ———- ———- ———- ———- —

STATUS FIRST_CHANGE# FIRST_TIM NEXT_CHANGE# NEXT_TIME

—————- ————- ——— ———— ———

1 1 39 52428800 512 1 YES

INACTIVE 4318162327 20-APR-19 4318209770 20-APR-19

3 1 40 52428800 512 1 NO

CURRENT 4318209770 20-APR-19 2.8147E+14

SQL> archive log list;

Database log mode Archive Mode

Automatic archival Enabled

Archive destination USE_DB_RECOVERY_FILE_DEST

Oldest online log sequence 39

Next log sequence to archive 40

Current log sequence 40

删除 redo log 文件

[oracle@testdb59 stdb59]$ rm -f *.log

然后非一致性关闭

SQL> shu abort

ORACLE instance shut down.

解决过程:

SQL> startup mount

ORACLE instance started.

Total System Global Area 1603411968 bytes

Fixed Size 2253664 bytes

Variable Size 1275071648 bytes

Database Buffers 318767104 bytes

Redo Buffers 7319552 bytes

Database mounted.

### 恢复丢失的 redo 文件,但是需要 open resetlogs 之后才能自动创建上!

SQL> recover database until cancel;

Media recovery complete.

尝试 resetlog 方式打开,如果报错如下,那么还得借助隐含参数_allow_resetlogs_corruption;

SQL> alter database open RESETLOGS;

alter database open RESETLOGS

*

ERROR at line 1:

ORA-01194: file 1 needs more recovery to be consistent

ORA-01110: data file 1: ‘/data/u01/app/oracle/oradata/stdb59/system01.dbf’

使用一个隐含参数_allow_resetlogs_corruption 强制启动数据库,设置此参数之后,在数据库 Open 过程中,Oracle 会跳过某些一致性检查,从而使数据库可能跳过不一致状态,到达 open 数据库的目的

SQL> create pfile=’/home/oracle/pfile.ora’ from spfile;

File created.

然后在 /home/oracle/pfile.ora 添加上

*._allow_resetlogs_corruption=true

SQL> startup mount pfile=’/home/oracle/pfile.ora’;

SQL> alter database open RESETLOGS;

Database altered.

然后一致性关闭数据库,去掉隐含参数_allow_resetlogs_corruption,重启数据库!

总结:不管是开归档还是没开归档,只要是非一致性关闭数据库,就需要借助隐含参数_allow_resetlogs_corruption,一致性关闭数据库恢复的话比较简单,启动到 mount 状态,重建丢失的 redo 文件即可!

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