oracle dba redo undo
日月明王BLOG:http://sunmoonking.spaces.live.com
在这里会介绍
UNDO
,
REDO
是如何产生的,对
TRANSACTIONS
的影响,以及他们之间如何协同工作的。
什么是
REDO
REDO
记录
transaction logs
,分为
online
和
archived
。以恢复为目的。
比如,机器停电,那么在重起之后需要
online redo logs
去恢复系统到失败点。
比如,磁盘坏了,需要用
archived redo logs
和
online redo logs
区恢复数据。
比如,
truncate
一个表或其他的操作,想恢复到之前的状态,同样也需要。
什么是
UNDO
REDO
是为了重新实现你的操作,而
UNDO
相反,是为了撤销你做的操作,比如你得一个
TRANSACTION
执行失败了或你自己后悔了,则需要用
ROLLBACK
命令回退到操作之前。回滚是在逻辑层面实现而不是物理层面,因为在一个多用户系统中,数据结构,
blocks
等都在时时变化,比如我们
INSERT
一个数据,表的空间不够,扩展了一个新的
EXTENT
,我们的数据保存在这新的
EXTENT
里,其它用户随后也在这
EXTENT
里插入了数据,而此时我想
ROLLBACK
,那么显然物理上讲这
EXTENT
撤销是不可能的,因为这么做会影响其他用户的操作。所以,
ROLLBACK
是逻辑上回滚,比如对
INSERT
来说,那么
ROLLBACK
就是
DELETE
了。
COMMIT
以前,常想当然地认为,一个大的
TRANSACTION
(比如大批量地
INSERT
数据)的
COMMIT
会花费时间比短的
TRANSACTION
长。而事实上是没有什么区别的,因为
ORACLE
在
COMMIT
之前已经把该写的东西写到
DISK
中了,我们
COMMIT
只是
1,
产生一个
SCN
给我们
TRANSACTION
,
SCN
简单理解就是给
TRANSACTION
排队,以便恢复和保持一致性。
2,
REDO
写
REDO
到
DISK
中(
LGWR
,这就是
log file sync
),记录
SCN
在
ONLINE REDO LOG
,当这一步发生时,我们可以说事实上已经提交了,这个
TRANSACTION
已经结束(在
V$TRANSACTION
里消失了)
3,
SESSION
所拥有的
LOCK
(
V$LOCK
)被释放。
4,
Block Cleanout
(这个
问题是产生
ORA-01555: snapshot too old
的根本原因)
ROLLBACK
ROLLBACK
和
COMMIT
正好相反,
ROLLBACK
的时间和
TRANSACTION
的大小有直接关系。因为
ROLLBACK
必须物理上恢复数据。
COMMIT
之所以快,是因为
ORACLE
在
COMMIT
之前已经作了很多工作(产生
UNDO
,修改
BLOCK
,
REDO
,
LATCH
分配),
ROLLBACK
慢也是基于相同的原因。
ROLLBACK
会
1
,恢复数据,
DELETE
的就重新
INSERT
,
INSERT
的就重新
DELETE
,
UPDATE
的就再
UPDATE
。
2
,
RELEASE LOCK
ROLLBACK
要比
COMMIT
消耗更多资源,因为
ORACLE
认为你一旦做数据更新,那么就意味着你要
COMMIT
(其他数据库不全是这种设计理念,比如
DB2
)
,所以在你更新数据的时候就做了大量的工作,这也可以理解为什么不建议用
TABLE
来做
TEMPORARY TABLE
。(
TEMP TABLE
消耗的
REDO
比固定表在
INSERT
时要少很多
,
UPDATE
时差不多是
1/2
,但是
DELETE
却相差无几
)
REDO
产生
REDO
越多,你的系统越慢,不但影响你自己的
SESSION
,还影响其他
SESSION
,
LGWR
管理
REDO
,并且是
TRANSACTION
的结束标志。
首先要知道怎么监控
REDO
,当然,
SET AUTOTRACE ON
可以,不过只能监控
DML
语句,而像
PROCEDURE
则无法监视。那么我们就需要观察字典了,
V$MYSTAT, V$STATNAME
,前面有两个脚本,
mystat
,
mystat2
SQL> @mystat "redo size"
NAME VALUE
---------------------------------------------------------------- ----------
redo size 1016784
SQL> insert into t select * from big_table;
已创建
46990
行。
SQL> @mystat2
NAME V
---------------------------------------------------------------- ----------
DIFF
----------------
redo size 6604308
5,587,524
看到产生了
5,587,524
的
REDO
,再对比下用
NOLOG
插入
SQL> @mystat "redo size"
NAME VALUE
---------------------------------------------------------------- ----------
redo size 6604308
SQL> insert /*+ APPEND */ into t select * from big_table;
已创建
46990
行。
SQL> @mystat2
NAME V
---------------------------------------------------------------- ----------
DIFF
----------------
redo size 6616220
11,912
看到
APPEND
插入用了
11,912
字节的
REDO
,比一般性插入要少很多。
或者用这个
PROCEDURE
也可以观察
SQL
消耗的
REDO
create or replace procedure do_sql( p_sql in varchar2 )
2 as
3 l_start_redo number;
4 l_redo number;
5 begin
6 select v$mystat.value
7 into l_start_redo
8 from v$mystat, v$statname
9 where v$mystat.statistic# = v$statname.statistic#
10 and v$statname.name = 'redo size';
11
12 execute immediate p_sql;
13 commit;
14
15 select v$mystat.value-l_start_redo
16 into l_redo
17 from v$mystat, v$statname
18 where v$mystat.statistic# = v$statname.statistic#
19 and v$statname.name = 'redo size';
20
21 dbms_output.put_line
22 ( to_char(l_redo,'9,999,999') ||' bytes of redo generated for "' ||
23 substr( replace( p_sql, chr(10), ' '), 1, 25 ) || '"...' );
24 end;
25 /
用法就不多说了。
减少
REDO
既然
REDO
这么消耗资源,那我们能屏蔽
REDO
吗?显然不能,那我们能减少
REDO
吗?这是可以的(注意,
9.2
以后,可以用
FORCE LOGGING
开关来控制是否强制
REDO
,如果
YES
,则不管
NOLOGGING
还是
APPEND
都是不起任何作用的,可以
SELECT FORCE_LOGGING FROM V$DATABASE
查看是否
FORCE
。另外需要明白,没有一个办法能彻底不记录
REDO
,只能是减少
REDO
。因为不管如何,数据字典总是要产生一些
REDO
的。
create table nologging as select xxx
新建的表没有原来表的索引和默认值
,
只有非空
(not null)
的约束素条件可以继承过来
.
INSERT /*+ APPEND */ INTO target_tablename SELECT
如果运行此命令时还有对
target_tablename
的
DML
操作会排队在它后面
,
对
OLTP
系统在用的表操作是不合适的。快速插入数据可以指定
append
提示,但是需要注意
noarchivelog
模式下,默认用了
append
就是
nologging
模式的。
在
archivelog
下,需要把表设置程
Nologging
模式。可以通过如下语句设置为
NO FORCE LOGGING
。
Alter database no force logging;
这两种方法转移数据时没有用
SGA
里数据缓冲区和事物处理的回滚段
,
也不写联机事物日志,就象数据库装载工具
SQLLOAD
一样直接把数据写到物理文件。
REDO
的问题
有时,会在
ALERT
中发现
Thread 1 cannot allocate new log, sequence 1466
Checkpoint not complete
Current log# 3 seq# 1465 mem# 0: /home/ora10g/oradata/ora10g/redo03.log
这问题出现在系统尝试
reuse online redo log file
但是却没有可用的。可能是由于
DBWR
没有完成
(Checkpoint not complete)
或
ARCH
没有完成。
1
,
DBWR
,用多
DBWR process
,合理分布数据,
2
,增加
REDO LOG FILE
3
,扩大
REDO
的大小
4
,让
CHECKPOINT
发生更频繁,可以减少
block buffer cache
,
FAST_START_MTTR_TARGET
,
LOG_CHECKPOINT_INTERVAL
,
LOG_CHECKPOINT_TIMEOUT
。(要考虑全面哟)