Oracle的Redo和Undo

延迟段创建:  
create table的时候,并没有真正分配段,而已等真正需要insert的时候才进行分配空间。
 
 
Update+ Commit所做的工作:

update:
  1. 生成undo信息
  2. 修改数据块
  3. 给数据块加锁标记,得到锁
  4. 生成Redo信息
commit:
  1. 为事务生成SCN,计数
  2. LGWR把Redo日志写入到磁盘 -- IO最花时间,  PLSQL中的Commit不会等LGWR写入磁盘,立刻返回。而其他的调用则需等待
  3. V$Transaction中删除事务记录
  4. V$Lock中记录的锁释放
  5. 清除块上的锁信息
所以commit过程的工作确实不多。
 
 
Update + Rollback所做的工作:
 
update:
  1. 生成undo信息
  2. 修改数据块
  3. 给数据块加锁标记,得到锁
  4. 生成Redo信息
rollback:
  1. 从undo读取数据,应用到数据块
  2. V$Transaction中删除事务记录
  3. V$Lock中记录的锁释放
  4. 清除块上的锁信息
  5. 清除Redo的缓存
Redo的测量
Redo语句以测量, redo的数量越多,系统就越慢。从DB Trace里面可以跟踪到, Redo是DB中的一个串行点,
 
 
Nologging:
不使用日志的情况,也就是不需要恢复数据。 比如索引的创建,即使介质出问题,索引还是可以重建。
 
 
临时表:
oracle的临时表,不会生成redo, 但是会生成undo.  所以他是不能恢复的。
临时表有支持多版本控制和并发,能够回滚,所以undo是必须的。
 
 
Truncate table和Delete Table:
我们都知道truncate table是很快,而delete table很慢。 一个主要原因是truncate是DDL,没有undo信息生成
 
 
 
Undo信息生成的DML排名
Insert语句生成很少的Undo,因为只为rowid生成Undo
update语句的Undo集中在被修改的字段上面, 而如果是带索引的字段修改,那么Undo是2.5倍
delete生成的Undo最多,整行的生成,所以开销是最大。  
 
所以避免在同步过程中执行delete的操作是一个好的编程习惯。
 
 
ORA-1555 Snapshot Too Old
这是一个经常见到的问题, 影响到查询语句,使收到这个错误的查询语句不能继续,它和数据破坏或者数据丢失完全没有关系,根本原因是提交得太过频繁。
由于读一致的存在,一个较长时间的查询访问到了一个undo块,但是由于undo的空间太少,这个undo块在后来的查询等待中,被其他的session所修改,那么这个查询就会返回这个错误。
 
为了避免这个问题,可以设置自动管理Undo  UNDO_RETENTION,让DB内置的"DBA"根据动态的数据来管理空间分配。
 

猜你喜欢

转载自zzhonghe.iteye.com/blog/2025665