理解粗浅,仅供参考
这里数据块指的都是缓冲区数据块
一致性读文章参考:http://hi.baidu.com/edeed/item/7aff6ee4b3f0870f8d3ea8b3
DUMP数据块文章参考:http://blog.163.com/dazuiba_008/blog/static/363349812012111111399549
ORACLE 9.2.0
DUMP的意思是查看一个数据块的内容
PLSQL命令窗口由ROWID查找数据块位置,普通权限用户
SQL> select t.*,dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) block# from test_user t;
ID AGE NAME FILE# BLOCK#
---------- ---------- --------- ---------- ----------
1 999 tommy 1 85546
2 999 jerry 1 85546
3 999 henry 1 85546
4 999 hibernate 1 85546
5 999 birt 1 85546
6 999 garden 1 85546
7 999 green 1 85546
8 999 green 1 85546
9 999 green 1 85546
10 999 green 1 85546
10 rows selected
对应文件号、块号
ALTER SYSTEM CHECKPOINT;手动刷新缓存到数据文件,没有这一步,物理文件可能与缓冲区内容不一致,DBWN参考http://blog.chinaunix.net/uid-24501667-id-3028586.html
ALTER SYSTEM DUMP DATAFILE 1 BLOCK 85546;生成BLOCK对应的TRACE文件
第一次DUMP生成一个.trc(TRACE)文件,以后的DUMP会把结果附加到文件里面,以时间分别。
进入LINUX ORACLE目录
$ pwd
/oracle/product/9.2.0/admin/***
$ ll
total 16
drwxr-xr-x 2 oracle oinstall 96 Jan 17 10:40 adump
drwxr-xr-x 2 oracle oinstall 4096 May 13 10:12 bdump
drwxr-xr-x 2 oracle oinstall 96 Jan 17 10:40 cdump
drwxr-xr-x 2 oracle oinstall 96 Jan 17 11:48 create
drwxr-xr-x 2 oracle oinstall 96 Jan 17 10:40 hdump
drwxr-xr-x 2 oracle oinstall 96 Jan 17 11:48 pfile
drwxr-xr-x 2 oracle oinstall 96 Jan 17 11:48 scripts
drwxr-xr-x 2 oracle oinstall 4096 May 23 14:23 udump
$
在*DUMP文件夹里面找。我的文件在UDUMP目录。
$ cd udump
$ ls -lt
total 176
-rw-r----- 1 oracle oinstall 18660 May 23 16:19 ***_ora_7997.trc
-rw-r----- 1 oracle oinstall 5582 May 23 10:23 ***_ora_3771.trc
-rw-r----- 1 oracle oinstall 1725 May 13 10:13 ***_ora_14056.trc
-rw-r----- 1 oracle oinstall 3720 Apr 19 18:41 ***_ora_1205.trc
-rw-r----- 1 oracle oinstall 3390 Apr 19 18:22 ***_ora_28836.trc
...
以更新时间排序。
然后可以more vi cat 看文件内容了。
先说说我对于一致性读的理解
一致性读文章参考:http://hi.baidu.com/edeed/item/7aff6ee4b3f0870f8d3ea8b3
SQL执行计划有Consistent gets 和 db block gets,很多文章说前者是读UNDO块,让人误解,其实这两个命名是有道理的。前者指需要保证一致性读从而读到的数据块,从而可能读到UNDO BLOCK,也可能不会,后者相反指不需保证一致性,完全从DATA BLOCK读取。比如SELECT必须保证一致性读,UPDATE不需要,会选择db block gets从数据块直接读。
借用上面链接的例子,分析一下数据块和ITL、UNDO块。
表TB1,1W条记录,第一万条记录在数据块在DB1,上一次更新在8:50,用户A在9:00遍历全表,需要15分钟到达最后一行,9:15读到的数据应该是9:00时刻的快照结果,而无论期间有没有更新,提交未提交。这就是一致性读。
9:00 DB1中的ITL信息为:SCN850 UNDO1/提交标志、事务号等
9:10用户B修改最后一行,不管提交未提交,DB1中ITL信息为:SCN910 UNDO2,其他
(更新与提交都会修改SCN,SCN结果会被修改两次,数据块头也有一个SCN,ITL中也有一个SCN,这些先不管)
ITL显示的信息是,数据块最后一次修改的流水号,此次修改以前数据保存的回滚段位置(更新数据会立即更新数据块,不管提交未提交,同时保存更新前数据到UNDO表空间),进入UNDO2,可以看到其中除了包含本次事务前的数据(或者其他能够完成回滚的操作数据),还有一个ITL,这个ITL是从数据块DB1里面复制过来的,DB1中更新ITL为SCN910之前先把其中数据复制到UNDO2,所以UNDO2中ITL为:SCN850 UNDO1,其他
9:11用户C修改数据块DB1,ITL变为:SCN911 UNDO3,其他
UNDO3中ITL为:SCN910 UNDO2,其他
9:15查询到数据块DB1时,发现SCN911大于查询SCN900,于是进入UNDO3,发现SCN910依然大过900,进入UNDO2,OK,然后由UNDO2和UNDO3里面的回滚操作数据组织出8:50DB1的数据,OK
ORA-01555快照过旧。更新数据如果提交的话,ITL有提交标志,提交后UNDO BLOCK允许被覆盖(这里超时时间好像可以设置)
如果9:10更新被提交,UNDO2标记已提交,然后9:12被其他事务覆盖,其中ITL为SCN912 UNDO4,其他
9:15查询到达的时候,根据UNDO3找到UNDO2块,发现其中SCN912大过UNDO3中的SCN911,抛出此异常。显然,根本重现不了9:00时刻的数据快照了。
-----------------------------------------------------------------------一致性读OVER----------------------------------------------------------------------------
-----------------------------------------------------------------------UPDATE做了哪些工作 开始------------------------------------------------------------------------
参考http://zhidao.baidu.com/question/480089238.html
个人理解。
UPDATE过程中主要实现两件事,行锁和回滚支持,这里只关心数据块的改动。
申请到undo资源,写入数据->在数据块头ITL表中申请一个空表项,写入数据->在每条要修改的记录行的行头写入申请到的ITL索引->更新数据
在四个SESSION中执行四条不同的UPDATE修改四条数据。几分钟后提交两条数据,另外两条未提交。
可见ITL中FLAG的--U--标志,意思是已提交但是提交操作在更新操作很久以后。
----是未提交。--C--是
--- flag 1 nibble ---- = transaction is active, or committed pending cleanout
--- C--- = transaction has been committed and locks cleaned out
--- -B-- = this undo record contains the undo for this ITL entry
--- --U- = transaction committed (maybe long ago); SCN is an upper bound
--- ---T = transaction was still active at block cleanout SCN
*** 2013-05-23 15:53:31.242
Start dump data blocks tsn: 0 file#: 1 minblk 85546 maxblk 85546
buffer tsn: 0 rdba: 0x00414e2a (1/85546)
scn: 0x0000.059dfd7b seq: 0x01 flg: 0x02 tail: 0xfd7b0601
frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
Block header dump: 0x00414e2a
Object id on Block? Y
seg/obj: 0xcabd csc: 0x00.59dfd09 itc: 4 flg: O typ: 1 - DATA
fsl: 0 fnx: 0x0 ver: 0x01
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0003.02d.0000ea56 0x0080002f.195a.13 ---- 1 fsc 0x0000.00000000
0x02 0x0002.00c.0000eb42 0x00800020.1bf1.27 ---- 1 fsc 0x0000.00000000
0x03 0x000a.00d.0000b2aa 0x0080029d.109e.47 --U- 1 fsc 0x0000.059dfd7b
0x04 0x0004.019.0000b27e 0x0080003e.16b2.2a --U- 1 fsc 0x0000.059dfd79
data_block_dump,data header at 0x8000000100193c8c
===============
tsiz: 0x1f70
hsiz: 0x26
pbl: 0x8000000100193c8c
bdba: 0x00414e2a
76543210
flag=--------
ntab=1
nrow=10
frre=-1
fsbo=0x26
fseo=0x1dc8
avsp=0x1ea6
tosp=0x1ea6
0xe:pti[0] nrow=10 offs=0
0x12:pri[0] offs=0x1ef3
0x14:pri[1] offs=0x1ee3
0x16:pri[2] offs=0x1e3c
0x18:pri[3] offs=0x1e28
0x1a:pri[4] offs=0x1e19
0x1c:pri[5] offs=0x1e08
0x1e:pri[6] offs=0x1df8
0x20:pri[7] offs=0x1de8
0x22:pri[8] offs=0x1dd8
0x24:pri[9] offs=0x1dc8
block_row_dump:
tab 0, row 0, @0x1ef3
tl: 16 fb: --H-FL-- lb: 0x1 cc: 3
col 0: [ 2] c1 02
col 1: [ 3] c2 0b 02
col 2: [ 5] 74 6f 6d 6d 79
tab 0, row 1, @0x1ee3
tl: 16 fb: --H-FL-- lb: 0x0 cc: 3
col 0: [ 2] c1 03
col 1: [ 3] c2 0b 02
col 2: [ 5] 6a 65 72 72 79
tab 0, row 2, @0x1e3c
tl: 16 fb: --H-FL-- lb: 0x2 cc: 3
col 0: [ 2] c1 04
col 1: [ 3] c2 0b 02
col 2: [ 5] 68 65 6e 72 79
tab 0, row 3, @0x1e28
tl: 20 fb: --H-FL-- lb: 0x3 cc: 3
col 0: [ 2] c1 05
col 1: [ 3] c2 0b 02
col 2: [ 9] 68 69 62 65 72 6e 61 74 65
tab 0, row 4, @0x1e19
tl: 15 fb: --H-FL-- lb: 0x4 cc: 3
col 0: [ 2] c1 06
col 1: [ 3] c2 0b 02
col 2: [ 4] 62 69 72 74
tab 0, row 5, @0x1e08
tl: 17 fb: --H-FL-- lb: 0x0 cc: 3
col 0: [ 2] c1 07
col 1: [ 3] c2 0a 64
col 2: [ 6] 67 61 72 64 65 6e
tab 0, row 6, @0x1df8
tl: 16 fb: --H-FL-- lb: 0x0 cc: 3
col 0: [ 2] c1 08
col 1: [ 3] c2 0a 64
col 2: [ 5] 67 72 65 65 6e
tab 0, row 7, @0x1de8
tl: 16 fb: --H-FL-- lb: 0x0 cc: 3
col 0: [ 2] c1 09
col 1: [ 3] c2 0a 64
col 2: [ 5] 67 72 65 65 6e
tab 0, row 8, @0x1dd8
tl: 16 fb: --H-FL-- lb: 0x0 cc: 3
col 0: [ 2] c1 0a
col 1: [ 3] c2 0a 64
col 2: [ 5] 67 72 65 65 6e
tab 0, row 9, @0x1dc8
tl: 16 fb: --H-FL-- lb: 0x0 cc: 3
col 0: [ 2] c1 0b
col 1: [ 3] c2 0a 64
col 2: [ 5] 67 72 65 65 6e
end_of_block_dump
其中行头lb指向的就是ITL索引
有几个事务,ITL就有几条记录
seg/obj:对象ID,查DBA_OBJECTS 可查到表名,进制转换to_char(123,’xxx’)、TO_NUMBER(’19F’,’XXX’)、bin_to_num(1,1,0,1)
bdba:数据块所在文件号和数据块号
0x00414e2a换成二进制0000 0000 0100 0001 0100 1110 0010 1010,取前十位是文件号,后面部分表示块号,14e2a的十进制为85546
nrow 该块上数据行数量
tl: 16行大小字节数 cc: 3列数 字节值由 DUMP(1,'16')或者 DUMP('TOMMY','16')得到,[]里面为字节数
XID 0x0003.02d.0000ea56
查V$TRANSACTION其中0003对应XIDUSN,02d对应XIDSLOT,0000ea56对应XIDSQN
UBA 0x00c02d8a.0090.20
->0000000011=3号文件,0x2d8a=11658号块,0x90=undo块被覆盖144次,0x20=第32条undo记录
-------------------------------------------------------------------UPDATE OVER-----------------------------------------------------------------------------
-------------------------------------------------------------------SELECT 开始-----------------------------------------------------------------------------
表TB1 9:00有两条记录都是ABC
9:10用户A改第一条为XYZ未提交
9:11用户B改第二条为UVW立即提交
9:15用户C查表结果为ABC、UVW
而数据块的记录很明显是XYZ、UVW
猜测,读取一行数据时,找到ITL,0自然就不管了,判断ITL提交状态,未提交时会进入UNDO BLOCK由此组织数据