Transaction Internals: 概述
首先,只有当在回滚段头(head of an undo segment)中分配得一个slot之后,一个事务(transaction)才能开始。这是一个事务(transaction)的物理表现(physical manifestation)。事务对应一个事务ID(txid),这个txid就是指向这个slot的一个指针。Txid的结构如下:
Txid = usn.slot.wrap
(undo_segment_number.transactionslot id.SCN wrap)
在一个事务(transaction)开始insert、update或者delete一个表中的数据行之前,包含此数据行的Block将被分配得一个ITL,这个ITL用于标志此数据行被锁定——直到事务提交或回滚。ITL中包含txid信息。
当事务修改数据快时,undo信息也同时创建并存储在回滚段中,回滚段头中对应于此事务的slot存储了指向这些undo信息的指针。
注:当查询v$lock视图时,id1字段——usn.slot;id2字段——SCN Wrap
Transaction Internal: Read Consistency
一致性读取(Read Consistency):
假设,前一个事务正在修改一数据块(事务还没有提交、回滚)时,另一个会话(session)要求读取此数据快中的数据。
后一个会话在读取数据块时(可能此数据快正在内存中),将发现数据快中的被打开的ITL。它检查事务的状态(通过读取回滚段头信息),将发现事务仍然是active状态。这就意味着,这个会话必须回推正在执行事务所作的操作,以获得此数据快在活动事务开始修改之前的内容。这被称为创建一个CR(ConsistentCopy) Copy。
从上面的描述中我们获致,一致性读取(Read Consistency)需要访问数据快、回滚段头、回滚段记录。任何一个部分出现Corruption,一致性读取都会受到影响。
Transaction Internal: Locking
Locking
继续上文中的例子,假设一个会话修改一个数据行,但是此数据行正在被前一个事务修改中,而且第一个事务还没有提交或回滚事务。
后一个会话在读取数据块时(可能此数据快正在内存中),将发现数据快中的被打开的ITL。它检查事务的状态(通过读取回滚段头信息),将发现事务仍然是active状态。这就说明这个时候不能更新此数据块,必须等待前一个事务结束(提交或回滚)。
由上文描述可知,Locking过程必须要能够访问回滚段头,如果回滚段头出现corruption,将会影响Locking。
Transaction Internal:Commit
Commit and Delayed Block Cleanout
我们继续前面的例子,假设第一个会话现在提交了(Committed)。这个将立即触发回滚段头中Transaction Table slot被标记为Inactive状态;但是,数据快本身可能并不会被立即修改以记录事务已经提交——这也就是说,在提交之后一段时间,数据快中的ITL可能仍然是打开(Open)的。
当RDBMS再去读取此数据快时,如我们前文所说的,将会去检查回滚段头中的Transaction Table中的slot,RDBMS此时会确认事务已经关闭了,这时候数据快中的ITL才会被RDBMS关闭。这就是所谓delayed block cleanout。如果这时候回滚段此时已经被删除,RDBMS会使用undo$中存储的SCN信息来确认事务是否被关闭。
注:由于RDBMS必须去读取回滚段头中的信息来确认事务是否已经被关闭,所以如果回滚段头中出现corruption,delayed block cleanout将会受到影响。
Transaction Recovery
事务恢复(回滚事务的处理过程)有下述几种情况:
l 当rollback 语句显示的被调用,由shadow process 执行Transaction Recovery。
l 当一个会话异常中断,由PMON执行Transaction Recovery。
l 在数据库打开时,由SMON或shadow process执行
Transaction Recovery:Rollback
当执行一个rollback语句,RDBMS将查找所有跟事务相关的undo记录,并且应用到数据库中。当语句结束后,事务所有的修改都被undone,并且ITL将会被清除。在rollback的时候没有delay。
Rollback操作需要访问回滚段头,undo records,数据快。任何一个出现corruption,rollback操作都会受到影响。执行回滚的操作会产生新的redo,将会被写到redo log中。
Transaction Recovery after a Process Crash
如果一个shadow process进程在事务处理中crash掉,PMON会探测到并立即回滚事务。可通过如下两个event来监测此操作:
10012tracename context forever,level 1
10246tracename context forever,level 2
Transaction Recovery: Instance Crash
如果RDBMS实例在某个事务还没有提交前crash掉,事务将没有机会回滚。在下次打开数据库的时候,crashrecovery将数据库rollforward,使得其恢复到实例crash之前的状态。然后由rollback recovery负责清除不一致的事务。
Transaction Recovery:Database Open
l 在system回滚段中的活动事务将会被立即rollback;
l 其他回滚段中的活动事务会被标记为dead;
l 稍后,SMON进程会再次搜索回滚段,将标记为dead的回滚段信息回滚;
在一次非正常的shutdown之后,RDBMS会经可能块的start up。这有利于减少宕机时间。另外一个好处时:如果一个新的事务试图更新被一个dead事务锁定的数据行时,新的事务会去回滚dead事务,而不必必须等待SMON进程。
此特性的一个侧面影响是:即使一个回滚段Corrupt了,数据库仍然能够打开,只是在alert日志中记录错误信息,由SMON进程产生一trace文件。
可用下述SQL语句查询deadtrasaction:
Select * from x$ktuxe where ktuxecfl=’DEAD’;
或者直接将回滚段头dump出来分析:
Alter system dump undo header R01;
Undo Segment Acquisition
l 在transaction recovery之后,实例会尝试获取回滚段:
n 在rollback_segments参数中指定的回滚段会被最先获取(acquisition)。
n 公共回滚段也会在需要的时候被获取。
l 获取如果出现错误,典型的是Ora-1545
如果回滚段的状态是‘Needs Recovery’,此回滚段将不能被实例获取,所以如果rollback_segments参数指定的回滚段中,如存在这样的回滚段,数据库将不能打开。
回滚段中存在dead transaction的可以被获取,用于记录新事务。
诊断事件:
10013——在startup时,监测Transaction Recovery
10015——在Transaction Recovery之前、之后分别dump回滚段头信息
使用隐藏参数:
_offline_rollback_segments
_corrupted_rollback_segments
System回滚段和已经在rollback_segments中列出的回滚段不能使用上述隐藏参数。
使用隐藏参数对RDBMS的影响
对打开数据库的影响
在打开数据库时,任何在这两个隐藏参数中出现的回滚段:
1. 不会被扫描,任一个活动的事务既不会被标记为dead也不会被回滚
2. 在dba_rollback_segs中标记为offline
3. 不能被实例获取,接受新的事务
4. 任何与_corrupted中出现的回滚段相关的分布式事务将被标记为’forced commit’
5. 通过更新pending_trans$和 dba_2pc_pending实现
对CR和Cleanout的影响
如果发现存在ITL和_offline中指定的回滚段相关,那么该回滚段将会被读取以获得事务的状态。
l 如果状态为Committed,cleanout。
l 如果状态是Active,并且你想读取数据快,将使用回滚段创建一个CR Copy。
l 如果状态是Active,并且你想Lock数据行,歇菜了,可能会死循环的。
如果发现存在ITL和_corrupted中指定的回滚段相关,回滚段不会被读取,事务状态不会被获取。
l 效果会和回滚段被drop一样,事务会被假定为committed,将执行delayed block cleanout。
l 如果事务并不是已经被提交的,那么logical corruption就出来了
所以,如果使用_corrupted参数,一定要重建数据库。
注:如果ITL在cleanout之后,我们去除_corrupted参数,如果你想roll back你刚才已经提交的数据快,测试证明,会导致数据快corruption
回滚段Corruption的恢复
l 任何情况下,介质恢复(Media Recovery)都是最好的选择,因为它保证一致性
当介质恢复不可用,才尝试使用其他手段,但是由此带来的危险性,最好在做之前有清楚的认识