oracle实施DML(事物过程)的深入研究(一)
用户所执行 DML (即执行事务)操作在 Oracle 内部按如下顺序进行。
1.相应事务分配回滚段( undo segment ), 这时优先使用当前联机状态的回滚段中一个。回滚段的选择是随机的,若另外的事务正在使用则重试 3 次, 在此过程中失败, 则将未联机的回滚段联机后使用。 如果此过程也失败, 就会创建新的回滚段, 通过这个过程也没有分配到回滚段, 则使用 Oracle 8i 中使用的回滚段( rollback segment ) 算法。即,使用另外事务使用中的回滚段中用量最少的回滚段。 如果服务器进程在获得回滚段时没有适当的联机状态的回滚段, 则等待 enq:US-contention 事件, 直到有适当的联机状态的回滚段为止。
2.分配回滚段后,在回滚段头上创建事务表 Slot ( transaction table slot )。
3.创建事务表后会生成 TXID ( Transaction ID ),再将此 TXID 分配给当前事务。 TXID 通过 V$TRANSACTION 视图的 XIDUSN 、 XIDSLOT 、 XIDSQN 表现, 这个值指向分给事务的回滚段头上存在的事务表的准确位置。事务必须在分配撤销区域后得到 TXID 。
4.事务对象的 数据块载入到高速缓冲区,在块头的 ITL ( Interested Transaction List )上登记事务条目( transaction entry )。如果 ITL 上没有登记条目所需的空间,直到有空间为止,一直等待 enq : TX-allocate ITL entry 事件。
5.将需要修改的块的修改信息存储到 PGA , 存储名为 Change Vector 。修改一行时,一般分别创建撤销头块( change vector#1 )、撤销块( change vector#2 )、 数据块( change vector#3 )相应的 change vector 。 进程将 PGA 的 change vector 以名为 redo record (或 redo entry )复制到重做缓冲区。在复制到重做缓冲区的过程中, 需获得 redo copy 锁存器、 redo allocation 锁存器、 redo writing 锁存器, 在此过程中若发生锁存器争用, 分别等待 latch: redo copy 、 latch: redo allocation 、 latch: redo writing 事件。
6.将之前映像信息( before image ) 记录到撤销块, 继而修改数据块, 被修改的数据块变为脏状态。 而且, 高速缓冲区上创建关于已修改的数据块的 CR ( consistent read ) 块。 如果需修改的行正在被另外事务所改变(即,修改后事务尚未结束的 状态), 就要等待事务结束, 此时会等待 enq:TX-row lock contention 事件。
7.执行提交( commit )后给事务分配 SCN ,提交信息存储在重做缓冲区。 9.重做缓冲区的内容记录在重做日志文件上,修改的块之后被 DBWR 记录到数据文件中。
8.回滚段头的事务表中存储已成功提交的信息,解除包括 TX 锁在内的所有资源占有。
事物执行用伪码表示如下:
//1.分配回滚段,优先从online undo space中分配
if(online undo segments no space){
for(i=0;i++,i<3){
//新事物从新循环申请三次回滚段
}
}
if(新事物还没有申请到空间){
//联机offline undo segments,从中分配空间
}
if(还没有申请到回滚段空间){
//使用rollback segment算法,使用另外事物使用中的回滚段中用量最少的回滚段
}
if(还没有申请到undo segments){
//则发生enq:US-contention等待事件,直到能够分配到适当的回滚段为止
}
//2.在分配到的回滚段头创建事物表Slot(transaction table slot)
//3.生成TXID(Transaction ID),并把TXID分配给当前事物
//4.往高速缓冲区载入事物对象关联的数据块,在块头的TIL(Interested Transaction List)上
登记事物条目(transaction entry)
if(如果块头上没有登记ITL所需空间){
//则发生enq:TX-allocate-ITL entry等待事件,直到有空间为止
}
//5.往PGA存储修改块的修改信息,以Change Vector的格式,Change Vector里面包含(创建撤销块头,撤销块,数据块信息)
进程将PGA的change vector 以名为redo record(或redo entry)复制到重做缓冲区
//6.将之前映像信息(before image)记录到撤销块,继而修改数据块,被修改的数据块变为脏状态
并且会在高速缓冲区中创建已修改数据块的一致读块
if(需修改的块正在被另外事物所改变){
//发生enq:TX-row lock contention等待事件
}
//7.执行提交(commit)后给事物分配SCN,提交信息存储在重做缓冲区。
//8.回滚段头的事物表中存储已成功提交的信息,解除包括TX锁在内的所有资源占用。
//9.重做缓冲区内容记录在redo log上,修改该的块之后被DBWR记录到数据文件中。