oracle 一致性读的研究

 

1oracle一致性读的背景知识

一致性读(Consistent Get)是Oracle一个非常优秀的特性.(当然它也是产生ora-1555错误的主要原因)在标准SQL中,为了防止并发事务中产生脏读,就需要通过加锁来控制.这样就会带来死锁、阻塞的问题,即时是粒度最小的行级锁,也无法避免这些问题.

为了解决这一矛盾,Oracle充分利用的回归段,通过会滚段进行一致性读取,即避免了脏读,又大大减少了系统的阻塞、死锁问题.

Oracle是如何实现一致性读的:

当Oracle更新数据块(Data Block Oracle中最小的存储单位)时,会在两个地方记录下这一更新动作.一个是在Redo Segment,.一个是回滚段UNDO Segment.并在数据块头部标示出来是否有修改数据.一个语句在读取数据快时,如果发现这个数据块是在它读取的过程中被修改的(即开始执行读操作时并没有被修改),就不直接从数据块上读取数据,而是从相应的回滚段条目中读取数据.这就保证了最终结果应该是读操作开始时的那一时刻的快照(snapshot),而不会受到读期间其他事务的影响.这就是Oracle的一致性读,也可以叫做多版本(Multi-Versioning).

 

2下面举例说明,oracle版本信息

SQL> select * from v$version

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

 

 

 

 

3undo 表空间信息

SQL> show parameter undo

NAME                              TYPE      VALUE

------------------------------------ ----------- ------------------------------

undo_management                 string     AUTO

undo_retention                        integer   3600

undo_tablespace              string     UNDOTBS1

 

4oracle11g,默认为我们创建10个undo 系统段信息。

SQL> select usn,name from v$rollname

  2  /

       USN NAME

---------- ------------------------------

        0 SYSTEM

        1 _SYSSMU1_592353410$

        2 _SYSSMU2_967517682$

        3 _SYSSMU3_1204390606$   

      .................................................

        9 _SYSSMU9_1735643689$

       10 _SYSSMU10_4131489474$

11 rows selected.                                                                                                           

 

5v$rollstat 目前还没有活动的信息(为节省篇幅,有省略)

SQL> select usn,latch,xacts,status from v$rollstat

  2  /

    USN LATCH       XACTS STATUS

---------- ---------- ---------- ---------------

        0        0             0 ONLINE

        1        0             0 ONLINE

        2        0             0 ONLINE

        3        0             0 ONLINE

        4        0             0 ONLINE

     ..      ...           ................

11 rows selected.

 

6也可以查看我们的v$transaction视图。

SQL> select xidusn,xidslot,status,name,ubafil,ubablk from v$transaction

  2  /

no rows selected

 

 

 

 

7我们创建如下的测试表

SQL> show user

USER is "SYS"

SQL> drop table t purge

  2  /

Table dropped.

 

SQL> create table t(id number)

  2  /

Table created.

作赋值操作。

declare

    i number;

begin

     for i in 1..100 loop

     insert into t values(i);

end loop;

end;

/

PL/SQL procedure successfully completed.

 

8此时在当前会话中,我们可以看到t表已经有值

SQL> select userenv('sid') from dual

  2  /

USERENV('SID')

--------------

           34

SQL> select count(*) from t

  2  /

  COUNT(*)

----------

       100

那么在其它会话中呢

SQL> select * from v$mystat where rownum<2

  2  /

       SID STATISTIC#    VALUE

---------- ---------- ----------

       38       0             0

SQL> select * from t

  2  /

no rows selected

可以看到没有值。这只是oracle为我们构造的一致性读,最简单的一个阐述。

 

9在sid为34的会话中作提交操作,在sid38中立即可见。这里不再赘述。

 

10对表t作如下操作

SQL> alter table t add ( name varchar2(20))

  2  /

 

Table altered

delete from t       

赋值:

declare

    i number;

begin

     for i in 1..100 loop

     insert into t(id,name) values(i,'hdp');

end loop;

end;

/

 

 

11在34号会话中

SQL> select * from t where rownum<10

  2  /

 

       ID NAME

---------- --------------------

        1 hdp

        2 hdp

        ..........

     ..........

        8 hdp

        9 hdp

 

9 rows selected.

 

SQL> update t set name='huangdp' where id=9

  2  /

 

1 row updated.

 

SQL> select * from t where rownum<10

  2  /

 

       ID NAME

---------- --------------------

        1 hdp

        2 hdp

        ..........

        8 hdp

        9 huangdp

 

9 rows selected.

12在38号会话中

SQL> select userenv('sid') from dual

  2  /

 

USERENV('SID')

--------------

           38

 

SQL> select * from t where rownum<10

  2  /

 

       ID NAME

---------- --------------------

        1 hdp

        2 hdp

        3 hdp

        .........

        9 hdp

 

9 rows selected.

 

 

13此时在v$transaction中有一未提交事务,就是我们刚刚的update操作。而sid为38

的会话,所查寻到的是undo段所构造的事务之前的镜像。

SQL> select addr,xidusn,status from v$transaction

  2  /

 

ADDR          XIDUSN STATUS

-------- ---------- ----------------

2E2BE6B8        1 ACTIVE

 

14利用rowid,找到这条数据在数据库文件的具体地址

SQL> select rowid,id,name from t where rownum<10

  2  /

ROWID                   ID NAME

------------------ ---------- --------------------

AAASqmAABAAAVZRAAA      1 hdp

AAASqmAABAAAVZRAAB      2 hdp

AAASqmAABAAAVZRAAC      3 hdp

.................................................      .........

AAASqmAABAAAVZRAAH      8 hdp

AAASqmAABAAAVZRAAI       9 huangdp

 

 

找到其具体所在的文件和block号

select dbms_rowid.rowid_relative_fno('AAASqmAABAAAVZRAAI') as file#,

        dbms_rowid.rowid_block_number('AAASqmAABAAAVZRAAI') as block#

  3    from dual;

 

     FILE#     BLOCK#

---------- ----------

        1    87633

从我们的事务视图中,也可以窥见一斑

SQL> select addr,xidusn,status from v$transaction

  2  /

ADDR          XIDUSN STATUS

-------- ---------- ----------------

2E2BE6B8        1 ACTIVE

 

 

让我们来dump 1号文件 87633号文件的数据,这个数据目前还是在内存中的

SQL> alter system dump datafile 1 block 87633

  2  /

System altered.

SQL> @?/gettrcname.sql

TRACE_FILE_NAME

------------------------------------------------------------------------------------------------------------------------------------

/opt/oracle/diag/rdbms/oa/oa/trace/oa_ora_4219.trc

查看这个4219的dump文件

主要是看ITL事务槽的信息


lck为1 表示锁定了一条数据,‘----’代表一个数据块正在被修改。

我们修改的是T表中第9行,看下转存文件中的row8(即第九行)


让我们来看看 68..75.. 代表什么

 

SQL> select chr(to_number('68','xx')) obj from dual

  2  /

OBJ

----

h

SQL> select chr(to_number('75','xx')) obj from dual

  2  /

OBJ

----

u

(注释:这里的75等,都是ASCII代码)

如上,该处存放的其实就是’huangdp’,这里存放的就是被修改的临时值。如此,我们也知道,

未提交的数据是在system表空间中的。具体其实是在buffer cache中。因为oracle会将需要的数据读到内存中来。并在内存中进行修改。

而其它会话,是去oracle构造的一致性读,即undo中去读取的数据,这数据所在的地址

就是uba

0x00c001e9.0114.2d

SQL> select to_number('00c001e9','xxxxxxxx') from dual;

 

TO_NUMBER('00C001E9','XXXXXXXX')

--------------------------------

                     12583401

 

select dbms_utility.data_block_address_file(12583401) as file#,

      dbms_utility.data_block_address_block(12583401) as block#

  3     from dual;

 

     FILE#     BLOCK#

---------- ----------

        3      489

 

dump这个文件

SQL> alter  system dump datafile 3 block 489

  2  /

 

System altered.

 

SQL> @?/gettrcname.sql

 

TRACE_FILE_NAME

------------------------------------------------------------------------------------------------------------------------------------

/opt/oracle/diag/rdbms/oa/oa/trace/oa_ora_4820.trc

 



 

我们直接查看这个文件,找到0x2d,可以看到存放的是hdp,其它会话就是从这里读值。



注释:

col1 表示第二列

【3】表示共有三个字符

file#3就是我们的undo表空间。

SQL> col file_name for a25

SQL> select file_name,file_id,tablespace_name from dba_data_files

  2  /

FILE_NAME               FILE_ID TABLESPACE_NAME

------------------------- ---------- ------------------------------

/huangdp/oa/users01.dbf    4 USERS

/opt/oracle/oradata/oa/un    3 UNDOTBS1

dotbs01.dbf

........................

 

 

至此,我们对oracle的undo,和一致性读有了一个深刻的认识。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值