ORA-1555错误综述

ORA-1555是一个非常著名但让人讨厌的错误,下面就该错误是如何产生的及该如何来预防做个综述。
ORA-1555错误简单的说就是针对一个数据块产生一致读时发生了错误。一致读就是指ORACLE利用回滚段来临时重构一个和事务或查询开始时的块状态相同的快照块的过程。如果一个块改变了多次,可能就会有多个快照块的。
一个事务或查询开始执行时,ORACLE会产生一个SCN来记录这个开始时刻点,这个SCN也就叫做SNAPSHOT SCN。ORACLE仅仅看基于SNAPSHOT SCN的快照记录。如果块中有活动的事务或BLOCK SCN> SNAPSHOT SCN时,就产生了一致读。如果是没有活动的事务但没有产生COMMIT SCN的块,先产生DELAY BLOCK CLEANOUT,再比较COMMIT SCN与SNAPSHOT SCN的大小,如果COMMIT SCN小于SNAPSHOT SCN则直接使用该块,否则要产生一致读。
产生ORA-1555的可能情况:
(1) 一个长时间运行的查询,并同时针对查询需要的块有DML处理
当一个长时间的查询开始执行时,查询所需要的一个数据块被修改并递交了,这个块是需要一致读的,但因为该DML事务已递交了,所以保留前映像的回滚段SLOT可以被另外的事务使用,这个查询事务耗时非常长,在这个时间段中,很可能该SLOT被另外的事务使用而把原值给覆盖了,所以当查询执行到该块时,该块的SNAPSHOT SCN时的值已经找不到了,报ORA-1555错误。
解决方法:
1、 业务控制,禁止对同一个表的长时间查询和更新处理同时进行,要分开执行
2、 增加回滚段的个数
3、 增大回滚段的大小,记住产生ORA-1555的错误可能是最小的回滚段造成的,所以每个回滚段的大小应该一致。
4、 不使用OPTIMAL选项
5、 推迟对DML语句的COMMIT
6、 缩短查询的时间,修改查询语句,比如并行查询
7、 为要查询的表建立只读SNAPSHOT,这样对表记录的修改就不会影响到查询,但该表不能是太大的表
(2) 交叉递交
通过一个游标建立一个循环来循环读取表的数据,但又在循环中对表的进行修改并递交。如果正好多次修改并递交,将一个数据块在回滚段的前映像给覆盖了,当循环又要取该数据块的值时,报ORA-1555错误。这是个经常出ORA-1555错误的操作。
解决方法:
1、 修改程序,避免这种情形出现
2、 尽量在循环读取中,不要做递交处理
3、 在查询语句中,增加“ order by 1 ”的语句,这样会在临时段中保留ORDER BY的结果,而不在需要一致读了。
(3) 延迟块清除
延迟块清除是指当一个DML事务发生并递交了,ORACLE在回滚段做了一个快速COMMIT标记该事务已递交了,但在DATA BUFFER中修改过的数据块并没有标记,(ORACLE一次只清除DATA BUFFER10%的修改的数据块)这些未清除但已递交的数据块要在下一次事务访问才清除掉,这就是延迟块清除。在这个过程中有可能出现ORA-1555的错误,但一般是非常难得的,因为出现这个错误需要满足以下几个条件:
1、已做了修改并递交,但又未做清除的数据块
2、这些块在被下一个要出错的事务使用前,没有被其他事务使用
3、查询期间,系统中又发生了大量的其他DML处理,这些DML处理不涉及到这些块。
4、因为这些大量的DML事务,产生了频繁的递交,造成事务表被多次WRAP,最初保留未清除事务的事务条目也被循环的使用,原来的UPDATE COMMIT SCN已经不存在了。
5、回滚段的最小SCN已经超过查询SCN了
6、当查询执行到该块的时候,发现该块的UPDATE COMMIT SCN已经不存在了,而且现在回滚段的最小SCN也比查询SCN要大,UPPER BOUND SCN都无法估算了,所以无法确定查询是否能使用这个块,造成ORA-1555错误。
解决方法:
一般这种情况很难出现,可以不考虑,如果确实要解决,可以在DML操作后,做一次FULL TABLE SCAN来清除上次未清除的块。
可以设置DELAYED_LOGGING_BLOCK_CLEANOUTS = true (缺省)
(4) 回滚段有坏块
总结,从上面说明中可以看出,防止ORA-1555问题出现,最根本的一点就是保证回滚段中已COMMIT的事务信息不被覆盖了。9I中,ORACLE提供一个更加有效的方法来保证这点,用参数UNDO_RETENTION来保证COMMIT的事务多长时间不被覆盖。具体说明,参见ORACLE9I的自动回滚段管理说明(SMU)

Oracle数据库备份与恢复实例

完全恢复
1、 控制文件没有镜像文件时的数据库恢复方法

Sql>startup nomount;
Sql>create controlfile DATABASE lijie
LOGFILE
GROUP 1 (/u01/redo11.log’,/u02/redo12.log’) SIZE 100,
GROUP 2 (/u01/redo21.log’,/u02/redo22.log’) SIZE 100,
GROUP 3 (/u01/redo31.log’,/u02/redo32.log’) SIZE 100
NORESETLOGS
Datafile
‘/u01/system01.dbf’,
…………………
Maxdatafiles 2000
Maxloghistory 2000
Maxlogmembers 5
CHARACTER SET ZHS16GBK;

2、 日志文件破坏时数据库恢复

Sql>startup mount;
Sql>alter DATABASE DROP logfile GROUP n(删除已经损坏的日志文件组)
Sql>alter DATABASE ADD logfile GROUP n
(‘u01/log4a.log’,
‘u01/log4a.log’)SIZE 2m;

3、 数据库在非归档方式时数据文件破坏的恢复

Sql>startup mount;
Sql>alter DATABASE datafile ‘/u01/lijie.dbf’ offline DROP;
Sql>alter DATABASE OPEN;

数据库可以正常使用,但数据文件中的数据永远不能恢复。

4、 数据库在归档方式时数据文件破坏的恢复
前提:lijie.dbf有备份

Sql>recover datafile ‘/u01/lijie.dbf’
Sql>alter DATABASE OPEN;

5、 数据库关闭时数据文件破坏的数据库恢复方法

一、 以mount方式启动数据库
Sql>startup mount
二、 将被破坏的数据文件的备份文件拷贝到相应目录、进行数据文件的恢复。
Sql>recover datafile ‘/u01/lijie.dbf’</code></blockquote>
再利用归档日志文件进行恢复!
 
6、 数据库运行时数据文件破坏的恢复
<blockquote><code>一、 ALTER DATABASE datafile ‘/u01/lijie.dbf’ offline;
二、 将被破坏的数据文件的备份文件拷贝到相应目录、进行数据文件的恢复。
Sql>recover datafile ‘/u01/lijie.dbf’
三、 利用归档日志进行恢复
四、 ALTER DATABASE datafile ‘/u01/lijie.dbf’ online;

不完全恢复
1、 恢复一个误删的表,删除时间为11点

一、 sql>startup mount;
二、 复制全部数据文件的备份文件
三、 Recover DATABASE until TIME ‘2004.09.16 10:30:00’
四、 再利用归档日志文件进行恢复
五、 ALTER DATABASE OPEN resetlogs
注意:数据库不完全恢复,日志序列号必须清零。
SELECT * FROM v$log; 查询v$log确认。

2、 删除表空间和表是不一样的,因为删除表空间时,表空间的数据文件就会脱离数据库。一旦数据文件脱离数据库,会引起控制文件改变。
一、 关闭数据库,复制未删除表空间之前的全部数据文件和全部控制文件,不得复制日志文件,否则数据库是同步的,不需要恢复
二、 Startup mount;
三、 检查跟踪文件,确认表空间删除时间为2004.09.06 12:00:00,确定恢复时间2004.09.06 11:40:00
四、

ALTER SESSION SET nls_date_format=’yyyy.mm.dd hh24:mi:ss’;
Sql>recover DATABASE until TIME ‘2004.09.06 11:40:00’

再利用归档日志进行恢复
五、

ALTER DATABASE OPEN resetlogs;

3、 在线日志破坏时的数据库恢复

一、 使用ALTER DATABASE chear清除日志内容
Sql>alter DATABASE clear unarchived logfile GROUP 1
如果还是不能正常使用,继续
二、 sql>startup mount;
SELECT * FROM v$log; 查询当前序列号
三、 复制全部数据文件、日志文件的备份文件
Sql>recover DATABASE until cancel;
基于撤消的数据库恢复,不得使用自动选项。
根据日志文件序号恢复到当前序列号。
四、 ALTER DATABASE OPEN resetlogs;

闪回技术简单使用

表的闪回

SQL> CREATE TABLE lijie
2 (name VARCHAR(20) NOT NULL PRIMARY KEY,
3 OLD INTEGER);
 
TABLE created.
 
SQL> SELECT * FROM lijie;
 
no ROWS selected
 
SQL> INSERT INTO lijie
2 (name,OLD)
3 VALUES('xiao',18);
 
1 ROW created.
 
SQL> SELECT * FROM lijie;
 
NAME OLD
-------------------- ----------
xiao 18
 
SQL> ALTER TABLE lijie enable ROW movement;(注意这一步不能少,很重要的!)
 
TABLE altered.
 
SQL> SELECT to_char(sysdate,'yyyy-mm-dd HH24:MI:SS') FROM dual;
 
TO_CHAR(SYSDATE,'YY
-------------------
2007-06-11 10:18:15
 
SQL> delete from lijie;
 
1 row deleted.
 
SQL> select * from lijie;
 
no rows selected
 
SQL> select * from lijie as of TIMESTAMP
2 TO_TIMESTAMP('2007-06-11 10:18:15','yyyy-mm-dd HH24:MI:SS');
 
NAME OLD
-------------------- ----------
xiao 18
 
SQL> insert into lijie
2 select * from lijie as of TIMESTAMP
3 TO_TIMESTAMP('2007-06-11 10:18:15','yyyy-mm-dd HH24:MI:SS');
 
1 row created.
 
SQL> select * from lijie;
 
NAME OLD
-------------------- ----------
xiao 18
回收站信息显示:
SQL> show recyclebin;
SQL> select * from user_recyclebin;
在回收站中查询到的表,可通过删除闪回进行恢复:
SQL>FLASHBACK TABLE lijie to BEFORE DROP;
永久性删除:
SQL>drop table lijie purge;
数据库闪回:
SQL>FLASHBACK DATABASE to scn 66666
SQL>FLASHBACK DATABASE to TIMESTAMP
TO_TIMESTAMP('2007-06-11 10:18:15','yyyy-mm-dd HH24:MI:SS');

Recovery Manager使用步骤

Recovery Manager

1、Backup命令可以将数据库备份分成多个数据包,每一个包称为一个备份子集,一个备份子集又可以分成多个备份片。
 
2、创建恢复目录
() 创建恢复目录数据库
() 创建RMAN用户并为用户授权
 
    CREATE USER rman IDENTIFIED BY rman
    GRANT CONNECT,resource TO rman
    GRANT recovery_catalog_owner TO rman
 
()创建恢复目录
 
    Rman catalog rman/rman
    CREATE catalog
 
如果不要使用默认表空间
 
    CREATE catalog tablespace cattbs;
 
3、 连接到目标数据库(有恢复目录)
(一)连接到目标数据库
 
    $rman target sys/change_on_install@网络连接串 catalog rman/rman
 
(二)注册数据库
 
    Rman>register DATABASE
 
(为了维持恢复目录与目标数据库控制文件的同步,在rman连接到目标数据库之后,必须运行resync catalog)
 
4、 rman命令
()使用copy命令进行数据库文件拷贝
 
    rman>copy datafile 2 TO ‘d:backupundotbs.dbf’
 
()显示文件的拷贝结果
 
    Rman>list copy
 
(三)使用backup命令备份表空间
 
    Rman>backup tablespace users;
 
()使用backup命令备份的结果
 
    List backup
 
(五)删除数据库备份文件
 
    DELETE backup
 
5、 手工通道配置
() 手工定义一个通道
 
    RUN
    {
    ALLOCATE CHANNEL C1 DEVICE TYPE sbt;
    BACKUP tablespace system;
    }
 
() 手工分配多个通道
 
    RUN
    {
    ALLOCATE CHANNEL C1 DEVICE TYPE disk;
    ALLOCATE CHANNEL C2 DEVICE TYPE disk;
    ALLOCATE CHANNEL C3 DEVICE TYPE disk;
    BACKUP DATAFILE 1,2,3;
    }
 
6、 通道控制参数设置
() FILESPERSET 用于备份时备份子集的文件个数
() MAXPIECESIZE 备份子集中备份片文件的大小
() MAXSETSIZE 备份子集的大小
() FORMAT 备份文件的存储格式
() RATE 通道I/O限制
7、 使用COPY备份数据文件和控制文件
 
    Rman>run
    {
    ALLOCATE CHANNEL C1 DEVICE TYPE disk
    ALLOCATE CHANNEL C2 DEVICE TYPE disk
    ALLOCATE CHANNEL C3 DEVICE TYPE disk
    Copy
    DATAFILE ‘/u01/*.dbf’
    To ‘/u02/*.dbf.bak’
    CURRENT CONTROLFILE to ‘/u02/control01.ctl.cp’;
    }
 
8、 backup备份数据库
(一)备份全部数据库
 
    BACKUP DATABASE FORMAT ‘/oracle/backup/%u’;
 
(二)备份表空间
 
    Run
    {
    ALLOCATE CHANNEL C1 DEVICE TYPE DISK
    FORMAT ‘/ORACLE/BACKUP/%U’;
    ALLOCATE CHANNEL C2 DEVICE TYPE DISK
    FORMAT ‘/ORACLE/BACKUP/%U’;
    BACKUP
    (
    TABLESPACE system,users,FILESPERSET 5)
    }
 
(三) 备份数据文件
 
    Rman>backup datafile 1,2,3,4 FILESPERSET 3
 
(四) 备份控制文件
 
    BACKUP CURRENT CONTROLFILE
 
(五) 备份归档日志
 
    BACKUP ARCHIVELOG
 
9、 多份数据备份
 
    SET BACKUP COPIES
    RUN
    {
    SET BACKUP COPIES=3;
    BACKUP DEVICE TYPE DISK
    FORMAT ‘backup1/%u’,’/backup2/%u’,’/backup3/%u’ TABLESPACE users;
    }
 
10、 Rman数据库恢复
 
    (一)用rman恢复数据库
    Sql>startup mount;
    Restore database;
    Recover database delete archivelog
    Skip tablsepace temp
    (二)恢复表空间
    1. Alter tablespace user offline;
    2. Restore tablespace user;
    3. Recover tablespace user;
    4. Alter tablespace user online;
    (三)恢复控制文件
    1. Startup nomount
    2. Restore controlfile;
    3. Alter database mount
    4. Restore database;
    5. Recover database;
    6. Alter database open resetlogs;
    (四)恢复一个没有备份的数据文件
    Alter database datafile ‘/u01/lijie.dbf’ offline
    Alter database create datafile ‘/u01/lijie.dbf’
    Recover datafile ‘/u01/lijie.dbf’(通过日志文件进行恢复)
    Alter database datafile ‘u01/lijie.dbf’ online