深入剖析oracle一致性读
2013-10-22 08:33
337 查看
首先开两个窗口:
transaction one:
Select * from users;
USERID USERNAME
------ --------------------
1 zbcxy
Transaction two:
select * from users;
USERID USERNAME
------ --------------------
1 zbcxy
Transaction one:
Update users set username=’xiongge’ whereuserid=1;
Select * from users;
USERID USERNAME
------ --------------------
1 xiongge
Transaction two:
Select * from users;
USERID USERNAME
------ --------------------
1 zbcxy
相信了解一致性读的朋友对上面的结果并不惊讶
下面我来剖析内部机制:
首先我们dump 当前block:
select id,name,dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid)from users;
DBMS_ROWID.ROWID_RELATIVE_FNO(DBMS_ROWID.ROWID_BLOCK_NUMBER(
------------------------------------------------------------
4 670
然后dump该数据块:
alter system dump datafile 4 block 670;
Block header dump: 0x0100029e
Object id onBlock? Y
seg/obj:0x126bb csc: 0x00.2ed461 itc: 2 flg: E typ: 1 - DATA
brn:0 bdba: 0x1000298 ver: 0x01 opc: 0
inc:0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0004.021.00000641 0x00c00163.0147.2d C--- 0
scn 0x0000.002e816a
0x02 0x0004.015.0000064f 0x00c0043d.0152.05 ---- 1 fsc 0x0000.00000000
bdba: 0x0100029e
data_block_dump,data header at 0x1fdc7064
===============
tsiz: 0x1f98
hsiz: 0x14
pbl: 0x1fdc7064
76543210
flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x1f64
avsp=0x1f76
tosp=0x1f76
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x1f64
block_row_dump:
tab 0, row 0, @0x1f64
tl: 14 fb: --H-FL-- lb: 0x2 cc: 2
col 0: [2] c1 02
col 1: [ 7] 78 69 6f 6e 67 67 65
end_of_block_dump
End dump data blocks tsn: 4 file#: 4 minblk 670maxblk 670
select UTL_RAW.CAST_TO_varchar2(replace(' 78 69 6f6e 67 67 65 ',' ')) from dual;
UTL_RAW.CAST_TO_VARCHAR2(REPLA
--------------------------------------------------------------------------------
Xiongge
可以看到数据块中的内容已经被修改,那么我们为什么在另一个会话中可以访问到原数据呢?
这取决与undo segment
Dump undo block:
Uba中保存着回滚快的地址
Alter system dump datafile 3 block 1085;
这里不明白的朋友请移步至:
http://www.hangger.com/index.php/archives/241
下面贴出undo block中的部分内容:
*-----------------------------
* Rec #0x5 slt: 0x15 objn:75451(0x000126bb) objd: 75451 tblspc: 4(0x00000004)
* Layer: 11 (Row) opc: 1 rci 0x00
Undo type: Regular undo Begin trans Last buffer split: No
Temp Object: No
Tablespace Undo: No
rdba: 0x00000000Ext idx: 0
flg2: 0
*-----------------------------
uba: 0x00c0043d.0152.01 ctl max scn:0x0000.002ec673 prv tx scn: 0x0000.002ec67d
txn start scn: scn:0x0000.00000000 logon user: 84
prevbrb: 12583992 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
compat bit: 4 (post-11) padding: 0
op: Z
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba:0x0100029e hdba: 0x0100029a
itli: 2 ispac: 0 maxfr: 4858
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0ckix: 0
ncol: 2 nnew: 1 size: -2
col 1: [ 5] 7a 62 63 78 79
select UTL_RAW.CAST_TO_varchar2(replace('7a 62 63 78 79 ',' ')) from dual;
UTL_RAW.CAST_TO_VARCHAR2(REPLA
--------------------------------------------------------------------------------
Zbcxy
这儿保存着我以前的数据。
那oracle是怎么判断该给用户什么数据呢?
当用户发出一条SQL语句,ORACLE就知道了它的结果,其实原因就在于ITL中记录的SCN,和Uba. 当发出一条sql语句时,ORACLE会记录下这个时刻(SCN),然后在buffer cache中查找需要的BLOCK,或者从磁盘上读,当别的会话修改了数据,或者正在修改数据,就会在相应的block上记录ITL,此时ORACLE发现ITL中记录的SCN大于SELECT时刻的SCN,那么ORACLE就会根据block中ITL中的Uba找到UNDO信息获得该block的前镜像,然后在buffer cache
中构造出CR块,此时ORALCE 也会检查构造出来的BLOCK中ITL记录的SCN,如果SCN还大于select时刻的SCN,那么一直重复构造前镜像,然后ORACLE找到前镜像BLOCK中的ITL的SCN是否小于select的SCN,同时检查这个事物有没有提交或者回滚,如果没有,那么继续构造前镜像,直到找到需要的BLOCK,如果在构造前镜像的过程中所需的UNDO信息被覆盖了,就会报快照过旧的错误。
transaction one:
Select * from users;
USERID USERNAME
------ --------------------
1 zbcxy
Transaction two:
select * from users;
USERID USERNAME
------ --------------------
1 zbcxy
Transaction one:
Update users set username=’xiongge’ whereuserid=1;
Select * from users;
USERID USERNAME
------ --------------------
1 xiongge
Transaction two:
Select * from users;
USERID USERNAME
------ --------------------
1 zbcxy
相信了解一致性读的朋友对上面的结果并不惊讶
下面我来剖析内部机制:
首先我们dump 当前block:
select id,name,dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid)from users;
DBMS_ROWID.ROWID_RELATIVE_FNO(DBMS_ROWID.ROWID_BLOCK_NUMBER(
------------------------------------------------------------
4 670
然后dump该数据块:
alter system dump datafile 4 block 670;
Block header dump: 0x0100029e
Object id onBlock? Y
seg/obj:0x126bb csc: 0x00.2ed461 itc: 2 flg: E typ: 1 - DATA
brn:0 bdba: 0x1000298 ver: 0x01 opc: 0
inc:0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0004.021.00000641 0x00c00163.0147.2d C--- 0
scn 0x0000.002e816a
0x02 0x0004.015.0000064f 0x00c0043d.0152.05 ---- 1 fsc 0x0000.00000000
bdba: 0x0100029e
data_block_dump,data header at 0x1fdc7064
===============
tsiz: 0x1f98
hsiz: 0x14
pbl: 0x1fdc7064
76543210
flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x1f64
avsp=0x1f76
tosp=0x1f76
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x1f64
block_row_dump:
tab 0, row 0, @0x1f64
tl: 14 fb: --H-FL-- lb: 0x2 cc: 2
col 0: [2] c1 02
col 1: [ 7] 78 69 6f 6e 67 67 65
end_of_block_dump
End dump data blocks tsn: 4 file#: 4 minblk 670maxblk 670
select UTL_RAW.CAST_TO_varchar2(replace(' 78 69 6f6e 67 67 65 ',' ')) from dual;
UTL_RAW.CAST_TO_VARCHAR2(REPLA
--------------------------------------------------------------------------------
Xiongge
可以看到数据块中的内容已经被修改,那么我们为什么在另一个会话中可以访问到原数据呢?
这取决与undo segment
Dump undo block:
Uba中保存着回滚快的地址
Alter system dump datafile 3 block 1085;
这里不明白的朋友请移步至:
http://www.hangger.com/index.php/archives/241
下面贴出undo block中的部分内容:
*-----------------------------
* Rec #0x5 slt: 0x15 objn:75451(0x000126bb) objd: 75451 tblspc: 4(0x00000004)
* Layer: 11 (Row) opc: 1 rci 0x00
Undo type: Regular undo Begin trans Last buffer split: No
Temp Object: No
Tablespace Undo: No
rdba: 0x00000000Ext idx: 0
flg2: 0
*-----------------------------
uba: 0x00c0043d.0152.01 ctl max scn:0x0000.002ec673 prv tx scn: 0x0000.002ec67d
txn start scn: scn:0x0000.00000000 logon user: 84
prevbrb: 12583992 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
compat bit: 4 (post-11) padding: 0
op: Z
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba:0x0100029e hdba: 0x0100029a
itli: 2 ispac: 0 maxfr: 4858
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0ckix: 0
ncol: 2 nnew: 1 size: -2
col 1: [ 5] 7a 62 63 78 79
select UTL_RAW.CAST_TO_varchar2(replace('7a 62 63 78 79 ',' ')) from dual;
UTL_RAW.CAST_TO_VARCHAR2(REPLA
--------------------------------------------------------------------------------
Zbcxy
这儿保存着我以前的数据。
那oracle是怎么判断该给用户什么数据呢?
当用户发出一条SQL语句,ORACLE就知道了它的结果,其实原因就在于ITL中记录的SCN,和Uba. 当发出一条sql语句时,ORACLE会记录下这个时刻(SCN),然后在buffer cache中查找需要的BLOCK,或者从磁盘上读,当别的会话修改了数据,或者正在修改数据,就会在相应的block上记录ITL,此时ORACLE发现ITL中记录的SCN大于SELECT时刻的SCN,那么ORACLE就会根据block中ITL中的Uba找到UNDO信息获得该block的前镜像,然后在buffer cache
中构造出CR块,此时ORALCE 也会检查构造出来的BLOCK中ITL记录的SCN,如果SCN还大于select时刻的SCN,那么一直重复构造前镜像,然后ORACLE找到前镜像BLOCK中的ITL的SCN是否小于select的SCN,同时检查这个事物有没有提交或者回滚,如果没有,那么继续构造前镜像,直到找到需要的BLOCK,如果在构造前镜像的过程中所需的UNDO信息被覆盖了,就会报快照过旧的错误。
相关文章推荐
- 基于 Red Hat 的发行版 Oracle Linux 正式发布Oracle Linux 7.1
- Oracle 10g R2不能使用EM的问题
- PreparedStatement中in子句的处理
- 基于 Red Hat 的发行版 Oracle Linux 正式发布Oracle Linux 7.1
- 数据库自动备份脚本
- 解决oracle用户连接失败的解决方法
- oracle的一些tips技巧
- Oracle 下的开发日积月累
- Oracle存储过程之数据库中获取数据实例
- Windows下ORACLE 10g完全卸载的方法分析
- Oracle 函数大全[字符串函数,数学函数,日期函数]第1/4页
- ORACLE LATERAL-SQL-INJECTION 个人见解
- Oracle Connect to Idle Instance解决方法
- oracle sys_connect_by_path 函数 结果集连接
- Oracle捕获问题SQL解决CPU过渡消耗
- oracle dba 应该熟悉的命令
- Oracle11.2 命令行手工最简创建数据库的过程
- Oracle 数据库自动存储管理-安装配置
- 基于oracle中锁的深入理解
- Oracle 数据库 临时数据的处理方法