DML操作oracle在内部实现

对与DML操作oracle在内部按如下顺序执行:
1,相应事务分配回滚段(undo segment).
2,分配回滚段后,在回滚段头上创建事务表slot(transaction table slot).
3.创建事务表后会生出TXID(TransactionID),再将TXID分配给当前事务。这个值
  指向分给事务的回滚段头上存在的事务表的准确位置。
4.事务对象的数据块载入到高速缓冲区,在块头的ITL(Intersted transaction list)上登记事务条目。
  如果itl上没有所需空间,就会发生等待enq:TX-allocate ITL entry。
5.将需要修改的块的修改信息存储到PGA,存储的方式是change vector,之后进程将PGA中的change vector
  以redo record复制到重做缓冲区。
6.将之前映像信息记录到撤销块,继而修改数据块,被修改的数据块变为脏状态。而且在高速缓冲区中创建
  以修改的数据块的CR块。
7.执行commit后给事务分配SCN,提交信息存储在重做缓冲区。
8.回滚段头的事务表中存储已成功提交的信息,结束包括TX锁在内的所有资源占有。
9.重做缓冲区的内容记录在重做日志文件上。
下面通过转储来探究一下这个过程:
会话1
SQL> update emp set sal=sal+100 where rownum=1;

 1 rows updated.
获得已执行update行位置
SQL> select rowid,dbms_rowid.rowid_relative_fno(rowid) as fno,
  2  dbms_rowid.rowid_block_number(rowid) as blkno
  3  from emp where rownum=1;

ROWID                     FNO      BLKNO
------------------ ---------- ----------
AAAQ+LAAEAAAAAfAAA          4         31

file number是4,block number是31,dump 这个block。

SQL> alter system dump datafile 4 block 31;

System altered.
SQL> l   
  1  SELECT    a.VALUE
  2         || b.symbol
  3         || c.instance_name
  4         || '_ora_'
  5         || d.spid
  6         || '.trc' trace_file
  7    FROM (SELECT VALUE
  8            FROM v$parameter
  9           WHERE NAME = 'user_dump_dest') a,
 10         (SELECT SUBSTR (VALUE, -6, 1) symbol
 11            FROM v$parameter
 12           WHERE NAME = 'user_dump_dest') b,
 13         (SELECT instance_name
 14            FROM v$instance) c,
 15         (SELECT spid
 16            FROM v$session s, v$process p, v$mystat m
 17*          WHERE s.paddr = p.addr AND s.SID = m.SID AND m.statistic# = 0) d
SQL> /

TRACE_FILE
--------------------------------------------------------------------
/opt/app/oracle/diag/rdbms/liqian/liqian/trace/liqian_ora_4118.trc

摘取trace文件如下:
 25 Dump of buffer cache at level 4 for tsn=4, rdba=16777247
     26 BH (0x26bed24c) file#: 4 rdba: 0x0100001f (4/31) class: 1 ba: 0x26968000
     --文件号是4,第31个block,cloass1是data block。
     27   set: 3 bsz: 8192 bsi: 0 sflg: 0 pwc: 0 lid: 0x00000000,0x00000000
     28   dbwrid: 0 obj: 69515 objn: 69515 tsn: 4 afn: 4
     29   hash: [0x26bf168c,0x32083a04] lru: [0x26bed9fc,0x26bed1dc]
     30   obj-flags: object_ckpt_list
     31   ckptq: [0x277f3330,0x273eb950] fileq: [0x32111f24,0x32111f24] objq: [0x30635f50,0x30635f50]
     32   st: XCURRENT md: NULL tch: 1
     33   flags: buffer_dirty block_written_once redo_since_read
     34           gotten_in_current_mode
     35   LRBA: [0x9.1625.0] LSCN: [0x0.b825b] HSCN: [0x0.b828c] HSUB: [1]
     36   cr pin refcnt: 0 sh pin refcnt: 0
     37   buffer tsn: 4 rdba: 0x0100001f (4/31)
     38   scn: 0x0000.000b828c seq: 0x01 flg: 0x00 tail: 0x828c0601
     39   frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
     95 Block header dump:  0x0100001f
     ----block头部信息
     96  Object id on Block? Y
     97  seg/obj: 0x10f8b  csc: 0x00.a5370  itc: 2  flg: E  typ: 1 - DATA
     98      brn: 0  bdba: 0x1000019 ver: 0x01 opc: 0
     99      inc: 0  exflg: 0
    100  
    101  Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
    102 0x01   0x0003.021.000002ac  0x00c00306.0192.23  ----    1  fsc 0x0000.00000000
    103 0x02   0x0008.01c.00000246  0x00c0072c.0163.1a  C---    0  scn 0x0000.000a5356
    ---ITL信息,事务id信息,第一行是我刚执行的未commit的事务标记,因为Flag上无任何标记信息,Lck
    为1,代表锁定的行数,也就是update的行数。
    105 data_block_dump,data header at 0x26968064
    106 ===============
    107 tsiz: 0x1f98
    108 hsiz: 0x2e
    109 pbl: 0x26968064
    110      76543210
    111 flag=--------
    112 ntab=1
    113 nrow=14
    114 frre=-1
    115 fsbo=0x2e
    116 fseo=0x1d14
    117 avsp=0x1d33
    118 tosp=0x1d33
    119 0xe:pti[0]      nrow=14 offs=0
    120 0x12:pri[0]     offs=0x1d14
    121 0x14:pri[1]     offs=0x1f47
    122 0x16:pri[2]     offs=0x1f1c
    123 0x18:pri[3]     offs=0x1ef3
    124 0x1a:pri[4]     offs=0x1ec6
    125 0x1c:pri[5]     offs=0x1e9d
    134 block_row_dump:
    ----block行信息
    135 tab 0, row 0, @0x1d14
    136 tl: 38 fb: --H-FL-- lb: 0x1  cc: 8
    -----lb是row上面的行lock byte信息,oracle用行级锁,lb是ox1为此事务的itl,当前行挂起的
    ITL编号。
    137 col  0: [ 3]  c2 4a 46
    138 col  1: [ 5]  53 4d 49 54 48
    139 col  2: [ 5]  43 4c 45 52 4b
    140 col  3: [ 3]  c2 50 03
    141 col  4: [ 7]  77 b4 0c 11 01 01 01
    142 col  5: [ 2]  c2 0a
    143 col  6: *NULL*
    144 col  7: [ 2]  c1 15
    145 tab 0, row 1, @0x1f47
    146 tl: 43 fb: --H-FL-- lb: 0x0  cc: 8
    147 col  0: [ 3]  c2 4b 64
    148 col  1: [ 5]  41 4c 4c 45 4e
    149 col  2: [ 8]  53 41 4c 45 53 4d 41 4e
    150 col  3: [ 3]  c2 4d 63
    151 col  4: [ 7]  77 b5 02 14 01 01 01
    152 col  5: [ 2]  c2 11
    153 col  6: [ 2]  c2 04
    154 col  7: [ 2]  c1 1f
    155 tab 0, row 2, @0x1f1c
    156 tl: 43 fb: --H-FL-- lb: 0x0  cc: 8
上面信息中ITL信息中,已经执行修改的事务在ITL上以itl=0x01记录。xid=0x0003.021.000002ac
转换成十进制。
xid=0x0003.021.000002ac三部分转换成十进制分别是USN=3,SLOT=33,SQN=684.

SQL> select*From v$mystat where rownum=1;


       SID STATISTIC#      VALUE
---------- ---------- ----------
       138          0          1
SQL> select xidusn,xidslot,xidsqn from v$transaction
  2  where addr=(select taddr from v$session where sid=138);


    XIDUSN    XIDSLOT     XIDSQN
---------- ---------- ----------
         3         33        684
转换后的信息和v$transaction里面的信息一致。XID=USN+SLOT+SQN
下面看看undo block dump的相关信息:
SQL> select xidusn,xidslot,xidsqn from v$transaction
  2  where addr=(select taddr from v$session where sid=138);

    XIDUSN    XIDSLOT     XIDSQN
---------- ---------- ----------
         3         33        684
回滚段编号3,事务表上slot位置是33.
SQL> select file_id,block_id from dba_rollback_segs where segment_id=3;

   FILE_ID   BLOCK_ID
---------- ----------
         3         41
SQL> alter system dump datafile 3 block 41;

System altered.
Elapsed: 00:00:00.13

SQL> SELECT    a.VALUE
  2         || b.symbol
  3         || c.instance_name
  4         || '_ora_'
  5         || d.spid
  6         || '.trc' trace_file
  7    FROM (SELECT VALUE
  8            FROM v$parameter
  9           WHERE NAME = 'user_dump_dest') a,
 10         (SELECT SUBSTR (VALUE, -6, 1) symbol
 11            FROM v$parameter
 12           WHERE NAME = 'user_dump_dest') b,
 13         (SELECT instance_name
 14            FROM v$instance) c,
 15         (SELECT spid
 16            FROM v$session s, v$process p, v$mystat m
 17           WHERE s.paddr = p.addr AND s.SID = m.SID AND m.statistic# = 0) d
 18  /

TRACE_FILE
--------------------------------------------------------------------------------
/opt/app/oracle/diag/rdbms/liqian/liqian/trace/liqian_ora_4118.trc
摘取trace文件:
23 Start dump data blocks tsn: 4 file#:4 minblk 31 maxblk 31
191   TRN TBL::
事务表信息
192  
193   index  state cflags  wrap#    uel         scn            dba            parent-xid    nub     stmt_num    cmt
194   ------------------------------------------------------------------------------------------------
195 
225 
226    0x1f    9    0x00  0x02ae  0x0006  0x0000.000b80c6  0x00c00305  0x0000.000.00000000  0x00000001   0x00000000  131    226 2254760
227    0x20    9    0x00  0x02ae  0x0018  0x0000.000b807d  0x00c00304  0x0000.000.00000000  0x00000001   0x00000000  131    227 2254760
228    0x21   10    0x80  0x02ac  0x0003  0x0000.000b79b0  0x00c00306  0x0000.000.00000000  0x00000001   0x00000000  
0x21转换成十进制是33,是上面执行事务的slot。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值