oracle事物
要想解释oracle事物的工作流程,首先先解释几个小概念:
1、undo段的组成:段头、回滚块
2、事物ID:每一个事物都有一个自己的事物ID,就像身份证号一样。
在v$transaction数据字典中xid就是事物ID,xid既是一个编号,也是一个地址,xid中内容的有
1、使用哪个回滚段的段头块;
2、一个undo段最多同时能有47个活动事物,一个undo段只有一个事物表,47个事物的情况都在事物表中 ,一个事物占用一行,此次事物使用47中的哪一行;
3、该行被覆盖的次数。这样就组成了唯一的事物ID。
3、事物表:undo表空间的undo段的第一个数据块(即undo段的段头块)里放事物表,共有47行。事物开始第一件事就是在事物表中找到一个空行,写上事物信息。也就是说undo段最多47个活动事物,但是oracle会尽量将一个事物放到一个段上,为了均匀分配(undo段的段头块的位置在dba_segments表空间可以查得)。
oracle中有哪些undo段:
4、事物槽:在每个数据块的块头部分有事物槽,事物槽包括xid、uba(undo block address)等等。
事物的工作流程:
当事物发生的时候,第一件事会在undo表空间的相对空闲的undo段的段头块的事物表中找到一个槽位,写上事物信息(xid),给这个事物分配一个undo块(undo块里写的就是修改之前的数据),然后将undo块的地址(即uba写到事物表中),所以现在事物表中有xid和uba;第二件事在要修改的数据块的块头的事物槽中找到槽位,写上事物信息(xid),(目的是通过数据块上的xid可以找到事物表),然后在将要修改的数据块上修改数据,修改之前的信息写到undo块里。同时,在事物槽中也写上uba地址,指向回滚块。为什么要在两个地方写事物信息呢?下面有解释。
当回滚块的数据写满之后,系统会自动分配一个回滚块,比如该事物修改了较多的数据,产生3个undo块,3个undo块有先后关系,它们会链起来,但是这是事物表中的uba就只是指向最新的undo块,这是便于回滚。
数据块的事物槽中的uba指向回滚数据,这便于构造CR块。
一个事物一个事物槽,只有当事物提交了,该事物槽才能被覆盖。
pctfree:1、当执行更新操作时,也许会占用pctfree的空间。2、当多个事物操作该数据块时,需要增加事物槽的数量,也会占用pctfree,但是如果事物过多,pctfree不够用了,(之前的事物槽未提交,就不能覆盖,该数据块又有新的事物产生,需要新的事物槽)这样就会产生事物槽争用的情况,大多数发生在update和delete的情况,insert不会发生。因为oracle会尽量的将insert插入的数据插入到多个块中,也就是平均一下,但是update和delete就无能为力了,因为这两个操作往往是针对某一行进行的,而某一行特定就是在这个块里。
如何查看该事物的undo块的位置和undo段头块的位置:
事物槽中的信息:
flag:是否提交
修改的数据块的行的头部指向事物槽,行的头部有事物槽的标记,在事物槽中有事物是否提交的标志,当第二个事物也要修改该行的数据时,发现该行的头部有前一个事物槽的标记,就知道了有事物修改该行,但是是否提交了呢,这时会找该块的事物槽(事物槽中有事物是否提交的标志),由此获知修改该行的先前的事物是否提交。在事物表和事物槽中都有事物信息和是否提交的信息是有作用的,因为如果只有事物表中有信息,那每次dml操作都必须要去查看事物表中的事物信息,会产生事物表的争用,再说在本身的数据块中就有,这样会很方便。
但是也会产生问题,例如一个事物修改1000各块,然后提交,但是要把这1000个块的事物槽的是否提交都要改成已提交,这样会造成提交的非常慢,所以oracle使用快速提交方式,oracle会将事物表中的是否提交标志进行更新,数据块中的事物槽的是否提交标志不更新或少量更新,所以回滚段的事物表的提交信息一定是最准确的,但是数据块的事物槽的是否提交信息不一定准确,如果显示已提交了,那么就一定提交了,若发现事物未提交,第二个事物就怀疑信息是否准确了,它会到回滚块的事物表中去查看(通过数据块的xid找到undo表空间的事物表),若发现事物表中的事物显示已提交,它不但会更新数据,还会将事物槽中的信息显示为已提交,再把该行的头部的事物槽指向第二个事物的事物槽,发现事物表中的事物显示未提交,那么就不会更新数据(行级锁)。sql server这种情况就不行了,sql server没有行级锁,只有块级锁,不能几个事物并发修改该数据块。
-------以上oracle事物的工作流程。
select过程中也许会产生redo,这是为什么呢?在select读块的过程中,如果发现该行的行头部指向某一事物槽(行级锁),它会找到该事物槽,然后查看是否提交,若显示已提交,那么就在读取数据的同时,删除行头部信息(取消行级锁),若事物槽显示未提交,则通过xid找到事物表(事物表中的信息是准确的),若显示已提交,那么在读的同时,会更改事物槽的提交情况,也会删除行头部信息(取消行级锁),若在事物表中显示未提交,那么就通过undo块中的行的数据和该块的未修改的数据一起构成CR块,然后读取CR块。所以select会使数据块发生改变,故而有可能产生redo的。