关于Oracle数据恢复的两个临界点

有的网友对我之前写的一篇技术博文中的描述提出了疑问,http://blog.itpub.net/23718752/viewspace-1436965/
其中的主要意思是:oracle中采用了undo+redo机制来作为数据恢复的基石,数据的恢复是通过前后台结合来实现的,在缓存级别,通过dbwr,能够把修改后的数据块刷入数据文件,这是一个异步的过程,不会因为发生数据变更就马上写入数据文件,同时存在log buffer,能够通过log buffer生成redo日志,最后通过lgwr把这部分变更刷到redo 日志,在这个过程中lgwr负责了保持数据完整性的任务,保证了数据不会丢失。
这句话再浓缩一下就是Oracle能够保证对于commit操作的数据都能够成功恢复。
今天可以通过两个特殊的场景来解释一下。
场景1:模拟Oracle ACID的异常情况,事务已经提交,但是redo log buffer还没有写到磁盘
第一个场景就是把lgwr写入redo的操作影响放大,操作时间延长。这个可以参考Jonathan Lewis的博客。https://jonathanlewis.wordpress.com/2011/08/19/redo-2/
这个场景被称为模拟Oracle ACID的异常情况,事务已经提交,但是redo log buffer还没有写到磁盘.我们来看看再下结论。
window #1: --打开一个窗口1,然后创建一个临时表t1
create table t1(n1 number);
insert into t1 values(1);
commit;

然后通过v$process查到对应的LGWR pid
n1@TEST11G>  select v$process.pid  from v$process  where pname='LGWR';
       PID
----------
        11

window #2 --打开窗口2,开启oradebug,绑定到lgwr上
sys@TEST11G> oradebug setorapid 11
Oracle pid: 11, Unix process pid: 11767, image: oracle@oel1 (LGWR)
sys@TEST11G>oradebug suspend 
Statement processed.

window #1--然后回到窗口1,做一个dml操作,commit
n1@TEST11G> update t1 set n1 = 2;
1 row updated.
n1@TEST11G> commit;

这个时候commit操作会一直hang在那儿

window #3  --开启第3个窗口,然后查看是否更新后的值已经可以成功查看。
sys@TEST11G> select count(*)from n1.t1;
  COUNT(*)
----------
         2
1 row selected. 

这个时候我们马上做类似断电的场景,shutdown abort
sys@TEST11G> shutdown abort
ORACLE instance shut down.

这个时候如果观察第一个窗口,会发现下面的错误,可以得知对应的session已经被强制释放了。
n1@TEST11G> commit;
ERROR:
ORA-03114: not connected to ORACLE
commit
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 15180
Session ID: 125 Serial number: 84

然后我们重启数据库
idle> startup
ORACLE instance started.
Total System Global Area  435224576 bytes
Fixed Size                  1337044 bytes
Variable Size             272632108 bytes
Database Buffers          155189248 bytes
Redo Buffers                6066176 bytes
Database mounted.
Database opened.

这个时候再查看数据,就会发现更新后的值已经丢失了。
idle> select *from n1.t1;
        N1
----------
         1
1 row selected.
对于这个问题,网上大家也是各有所见,有的说commit没有成功返回,就不算是一个完整的事务,没有恢复是可以理解的。有的说,这个是Oracle对于数据恢复的一个灰色地带。
我的意见是首先这是一个测试,把整个过程放慢,影响放大了,整个过程处于一个快要提交但是还没有提交的边界。这部分内容还是没有写入redo中的。只是从缓存中完成了整个数据变更的过程。
commit在这个放慢的临界点没有完成,严格意义上应该不属于一个完整的事务。

上面这个案例是通过debug的方式来做的,我们来用另外一个场景来模拟一下,看看实际中可能碰到的场景如果出现类似问题,redo是否依旧可靠。

场景2:模拟Oracle 归档满的临界点,事务是否依然能够成功提交,成功恢复
我们来模拟在归档日志满的时候,无法再写入redo,依旧可以成功commit,但是数据是否能够成功恢复的案例。
我们在测试环境简单模拟一下归档满的临界点,查看磁盘空间,归档所在的挂载点还有6G的可用空间。
[ora11g@oel1 archivelog]$ df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda3              30G   23G  6.0G  79% /u02
none                  690M  104K  690M   1% /var/lib/xenstored

我们来使用dd来创建一些dummy文件。
[ora11g@oel1 archivelog]$ time dd if=/dev/zero bs=1M count=5000 of=direct_5000M
5000+0 records in
5000+0 records out
5242880000 bytes (5.2 GB) copied, 224.21 seconds, 23.4 MB/s
real    3m44.222s
user    0m0.024s
sys     0m20.317s
创建后再逐步缩小范围。
[ora11g@oel1 archivelog]$ time dd if=/dev/zero bs=1M count=1000 of=direct_1000M
[ora11g@oel1 archivelog]$ time dd if=/dev/zero bs=1M count=100 of=direct_100M
最后发现空间都被占用完了。

[ora11g@oel1 archivelog]$ df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda3              30G   29G     0 100% /u02
直到没有空间可用我们才收手。
[ora11g@oel1 archivelog]$ time dd if=/dev/zero bs=1M count=10 of=direct_10M
dd: writing `direct_10M': No space left on device
1+0 records in
0+0 records out
0 bytes (0 B) copied, 0.000909 seconds, 0.0 kB/s
最后生成的dd文件如下:
-rw-r----- 1 ora11g dba   33485824 May 20 15:30 1_4_879784710.dbf
-rw-r--r-- 1 ora11g dba 5242880000 May 20 15:36 direct_5000M
-rw-r--r-- 1 ora11g dba 1048576000 May 20 15:37 direct_1000M
-rw-r--r-- 1 ora11g dba  104603648 May 20 15:38 direct_100M
-rw-r--r-- 1 ora11g dba          0 May 20 15:39 direct_10M

使用sqlplus报出下面的错误,这样我们就可以开始这个临界点的测试了。
sys@TEST11G> conn n1/n1
ERROR:
ORA-00257: archiver error. Connect internal only, until freed.
sys@TEST11G> create table aa as select *from cat;
Table created.
sys@TEST11G> insert into aa select *from aa;
4856 rows created.
sys@TEST11G> commit;
Commit complete.
sys@TEST11G> insert into aa select *from aa;
9712 rows created.
sys@TEST11G> commit;
Commit complete.
sys@TEST11G> select count(*)from aa;
  COUNT(*)
----------
     19424

可以看到这个过程中还是能够成功commit数据的。查取更新都可以使用顺利完成。
可以再开一个窗口运行alter system switch logfile做几个日志刷新。发现这个时候日志刷新也hang住了。

看看alert日志,发现已经提示空间不够,无法生成归档日志了。
Wed May 20 15:43:59 2015
Errors in file /u02/ora11g/diag/rdbms/test11g/TEST11G/trace/TEST11G_arc1_13247.trc:
ORA-19504: failed to create file "/u02/ora11g/flash_recovery_area/TEST11G/archivelog/1_5_879784710.dbf"
ORA-27044: unable to write the header block of file
Linux Error: 28: No space left on device
Additional information: 3
ARC1: Error 19504 Creating archive log file to '/u02/ora11g/flash_recovery_area/TEST11G/archivelog/1_5_879784710.dbf'
ARCH: Archival stopped, error occurred. Will continue retrying
Non critical error ORA-00001 caught while writing to trace file "/u02/ora11g/diag/rdbms/test11g/TEST11G/trace/TEST11G_arc1_13247.trc"
Error message: 
Writing to the above trace file is disabled for now on...
ORACLE Instance TEST11G - 

这个时候我们继续模拟一个断电场景shutdown abort.
原有的日志刷新也会自动终止。
ERROR:
ORA-03114: not connected to ORACLE
alter system switch logfile
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 9686
Session ID: 125 Serial number: 480

如果这个时候启动到open阶段就会自动停止,原因就是归档空间的问题。
我们做一个小改动。腾出一小部分空间来。
[ora11g@oel1 archivelog]$ rm direct_100M
然后再次尝试启动数据库就没有问题了
idle> alter database open;
Database altered.
这个时候查看归档路径下,会发现已经生成了3个归档文档
-rw-r--r-- 1 ora11g dba 5242880000 May 20 15:36 direct_5000M
-rw-r--r-- 1 ora11g dba 1048576000 May 20 15:37 direct_1000M
-rw-r--r-- 1 ora11g dba          0 May 20 15:39 direct_10M
-rw-r----- 1 ora11g dba       2048 May 20 15:55 1_6_879784710.dbf
-rw-r----- 1 ora11g dba     204800 May 20 15:55 1_5_879784710.dbf
-rw-r----- 1 ora11g dba    1808384 May 20 15:55 1_7_879784710.dbf
这个时候发现对于这些信息变更已经成功刷新到了归档中。这样就为数据恢复提供了强有力的基石,保证了数据在commit成功的情况下能够成功恢复。

时间: 2024-10-24 20:33:31

关于Oracle数据恢复的两个临界点的相关文章

Oracle数据恢复顾问(Data Recovery Advisor)

Oracle数据恢复顾问用于当数据发生错误或故障时,进行自动收集数据故障信息,并生成恢复脚本,用于完成数据恢复.数据恢复顾问也可以主动检查故障. 在这种模式下,它可以在数据库进程发现数据损坏并发出错误之前进行潜在的检测并分析数据故障.数据故障可能非常严重. 例如,如果您当前的日志文件丢失,则无法启动你的数据库. 一些数据故障(如数据文件中的块损坏)不是灾难性的他们不会将数据库关闭或阻止您启动Oracle实例. 数据恢复顾问处理这两种情况:当您无法启动数据库时(因为某些情况)所需的数据库文件丢失,

oracle10-关于oracle同时往两张表添加数据的问题

问题描述 关于oracle同时往两张表添加数据的问题 语句如下 declare sacn varchar2(15) :='111'||lpad(seq_no.nextval,12,0); begin insert all into customer(costomer_no,costomer_type) values(sacn,'P') into person(costomer_no,name,tel,address) select ****,ps.name,ps.tel,ps.address f

java中用jdbc获取oracle数据分两次返回,两次返回的时间间隔为两个小时

问题描述 近日,在生产系统出现了三次同样的问题:问题如下:有个每十分钟起的一个java线程,这个线程启动一个任务,任务的作用是通过spring3.1.1的jdbc包的连接池向oracle(11gR2版本)小版本号为11.2.0.1,发送多个查询,其中某个查询假如此查询会返回10w条记录,但是查询瞬间会先返回8万条记录,在整整两个小时后会将剩下的2w条数据给完整返回.上述oracle出现的情况是oracle工程师经过后台分析和看日志之后给出的详细数据,整整两个小时后剩余的数据才返回.此种情况在生产

oracle创建存储过程两种方法

oracle创建存储过程两种方法 create or replace procedure getdefault is begin   execute immediate ' create global temporary table deftemp(pid varchar2(5))on commit delete rows';   select * from deftemp; end //方法二 /* 下面来看个 1:创建临时表 2:往临时表中插入结果集 3:返回临时表的结果集 oracle存储

Oracle中对两个数据表交集的查询

oracle|数据 Oracle关系型数据库管理系统是世界上流行的关系数据库,它是一个极其强大.灵活和复杂的系统,据说,在使用oracle时应有这样的思想,那就是在SQL中几乎可以实现任何一种想法. 下面向大家介绍使用SQL查两个Oracle数据表查询的相同数据的方法,笔者感到这两种方法执行效率高.使用方便. 第一种方法:利用操作符intersect intersect操作符用来合并两个查询,返回两个查询中都存在的记录,即返回两个查询结果的交集,前提是两个查询的列的数量和数据类型必须完全相同.

oracle体系结构的两个基本概念

要了解oracle体系结构必须先了解两个基本的概念: 数据库和实例.一: 数据库数据库(database)是一个数据集合.无论数据库是采用关系结构还是面向对象结构, oracle数据库都将其数据存放在数据文件中. 在其内部, 数据库结构数据对文件的逻辑映射, 使不同的数据分开存储, 这些逻辑划分称为表空间. 表空间和文件介绍:1: 表空间表空间(tablespace)是数据库的逻辑划分, 每个数据库至少有一个表空间,叫做系统表空间(system 表空间). 一个表空间只能属于一个数据库.每个表空

Oracle数据恢复:kcbz_check_objd_typ_3 错误处理

在一次数据恢复之后,遇到了ORA-00600 kcbz_check_objd_typ_3错误,在此记录一下. 首先 kcbz_check_objd_typ_3 这个错误的含义是: 当Oracle在检查内存中的数据块时,发现数据块上的对象号是错误的,随之抛出kcbz_check_objd_typ_3 这个异常. 通常这个错误意味着存在着数据损坏. 在我们遇到的案例中,用户首先是由于存储损坏引入的问题,我们修复后出现这个错误,这个错误在后台执行AWR采样时触发,临时性的,我们可以禁用AWR采样,从而

oracle数据库最近两小时数据文件及io统计信息

select e.tsname, substr(e.filename, 1, 52) filename, e.phyrds - nvl(b.phyrds, 0) reads, (e.phyrds - nvl(b.phyrds, 0)) / (SELECT EXTRACT(DAY FROM E.END_INTERVAL_TIME - B.END_INTERVAL_TIME) * 86400 + EXTRACT(HOUR FROM E.END_INTERVAL_TIME - B.END_INTERV

Oracle数据恢复: 50TB ASM crash例子

某客户50 TB的ASM发生故障,经过合力拯救,恢复正常,在此简单记录一下!实际上最后发现比我想象中的简单的多.如下是关于该故障的详细描述情况. –db alert log信息 Mon Jul  6 15:17:43 2015 Errors in file /oraclehome/admin/xxxx/udump/xxxx_ora_262606.trc: ORA-27063: number of bytes read/written is incorrect IBM AIX RISC Syste