关于Oracle数据恢复的两个临界点(r5笔记第42天)

有的网友对我之前写的一篇技术博文中的描述提出了疑问,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成功的情况下能够成功恢复。

原文发布于微信公众号 - 杨建荣的学习笔记(jianrong-notes)

原文发表时间:2015-05-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏magicsoar

C++操作mysql方法总结(2)

C++通过ODBC和通过MFC ODBC操作mysql的两种方式 使用vs2013和64位的msql 5.6.16进行操作 ? 项目中使用的数据库名和表数据请参...

28660
来自专栏linux驱动个人学习

耳机驱动程序上报

17420
来自专栏不想当开发的产品不是好测试

centos6.6 下安装mysql

背景 没啥好说的,就是需要搭建自己的测试数据库跟研发的数据隔离开来,需要怼mysql 步骤 1. 确认线上mysql的版本 SELECT VERSION(); ...

23450
来自专栏大宽宽的碎碎念

怎么避免MYSQL误删除避免混淆开发环境的DB和生产环境的DB用事务保护使用安全更新模式对DROP和TRUNCATE慎之又慎最终的招数最终的话

376130
来自专栏大内老A

谈谈基于Kerberos的Windows Network Authentication[下篇]

六、User2User Sub-Protocol:有效地保障Server的安全 通过3个Sub-protocol的介绍,我们可以全面地掌握整个Kerberos的...

23570
来自专栏重庆的技术分享区

如何在Debian 8上安装MySQL

MySQL是一种流行的数据库管理系统,用于Web和服务器应用程序。本指南将介绍如何在运行Debian 8(Jessie)的Linode上安装,配置和管理MySQ...

96920
来自专栏杨建荣的学习笔记

一个闪回区报警的数据恢复(r11笔记第62天)

今天在火车上接到一个电话说,数据库有个报警,让我看看是怎么回事。 看着报警信息一直重复出现,看来是有些问题了。 这是一个统计库,出现了DG相关的...

27550
来自专栏java系列博客

pl/sql导入excel到oracle表

23570
来自专栏运维技术迷

MySQL数据库(一):安装MySQL数据库

安装环境: 操作系统版本:RHEL 6.5 安装版本:MYSQL 5.1 升级版本:MYSQL 5.6 一、简述MYSQL 1.什么是数据库? DB ...

45380
来自专栏数据和云

【合理授权,安全第一】聊一聊Oracle数据库的用户权限

编辑手记:年底大家最关注数据安全,之前我们说过,数据库的风险分为外部风险和内部风险。外部风险无法预估但概率较小,平时发生最多的还是内部操作的风险,因此合理控制权...

27850

扫码关注云+社区

领取腾讯云代金券