在oracle中 当一个用户去读数据时,是不是读的都是commit后的数据? 而且是先去undo里面找,undo里面没有的话,再去磁盘里面找啊? 未commit的数据 是否也能从undo里面读到呢? 谢谢!

解决方案 »

  1.   

    关注..,我也在刚开始学oracle 
      

  2.   

    在oracle中 当一个用户去读数据时,是不是读的都是commit后的数据? 
    是。
    而且是先去undo里面找,undo里面没有的话,再去磁盘里面找啊?
    不是。未commit的数据 是否也能从undo里面读到呢?
    不能。
      

  3.   

    没有commit的数据一般还在数据缓冲区中。不会在undo里的。
      

  4.   

    我与楼上两位意见不相同, 提下我的看法:我认为能从undo中读数据, 
    一个用户用去读的时候, 是可以读到自己未提交的数据的
    比如默认情况下
    update emp set empno = 1;
    不提交,再select empno from emp, 这里是读到的empno全是1
    如果此时别人去读, 那么读的是undo
    而能不能读到别人未提交的数据, 这需要看oracle事务隔离级别是怎么设置的是否放在缓冲区, 由缓存策略决定不对的话大家指点
      

  5.   

    是说“未commit的数据 是否也能从undo里面读到呢?  不能”。这个看法不同吗?
    未commit的数据,要么在buffer cache中,要么被写入数据文件中。但是肯定不会进入UNDO的。我认为能从undo中读数据, 
    一个用户用去读的时候, 是可以读到自己未提交的数据的
    这个自然能读。但是这个读要么直接读缓冲区;要么先去把该表脏数据所在数据文件对应数据块读入缓冲区。而能不能读到别人未提交的数据, 这需要看oracle事务隔离级别是怎么设置的 
    ORACLE中不同会话不能读取对方未提交的数据。ORACLE是严格通过ACID测试的,如果这样,那隔离性就通不过了。不存在“oracle事务隔离级别是怎么设置的”来做设置。ORACLE没有什么“事务隔离级别设置”选项。是否放在缓冲区, 由缓存策略决定 
    也没“缓存策略”这个说法吧?脏数据开始肯定在buffer cahce中。当dbwr被触发时,就被写入到脏数据对应表的数据块中了。“缓存策略”指什么呢?
      

  6.   

    oracle没有read uncommitted的设置, 这个我没有做过实验一直理解错了
    那么就是别人无法读到未提交的数据, 谢谢vc555大哥指点SQL> alter session set isolation_level= serializable;Session altered.SQL> alter session set isolation_level = read uncommitted;
    Alter session set isolation_level = read uncommitted
                                             *
    ERROR at line 1:
    ORA-02183: valid options: ISOLATION_LEVEL { SERIALIZABLE | READ COMMITTED }关于另外两点, 我还有些疑问
      

  7.   

    另外两个问题是否放在缓冲区, 由缓存策略决定
    也没“缓存策略”这个说法吧?脏数据开始肯定在buffer cahce中。当dbwr被触发时,就被写入到脏数据对应表的数据块中了。“缓存策略”指什么呢?如果数据更改很久没有提交, 脏数据很多, 导致缓冲区满了, 那么会不会写硬盘呢? 
    有没有一个策略来控制谁进谁出内存呢? 
      

  8.   

    呵呵。有问题大家讨论。看来LS的还用过别的RDBMS。如果数据更改很久没有提交, 脏数据很多, 导致缓冲区满了, 那么会不会写硬盘呢? 
    有没有一个策略来控制谁进谁出内存呢? 
    会写硬盘啊,就是写数据文件。这个策略就是我说的“当dbwr被触发时”。被触发的条件有7个,而“脏数据很多, 导致缓冲区满了”就是其中一个触发条件。
      

  9.   

    我觉得我可以提这样的一个问题, 来把情况搞清楚, 
    呵呵, slepzzzzz和linzhangs也说两句啊, 
    继续支持vc555讲课现在我开两个sqlplus, 一个A另一个B
    A执行这样的伪代码:
    for (int i=0; i<= 10000000000; i++)
    {
        update emp set empno = i;
    }保证循环很多次, 让缓存放不下所有脏数据.
    那么包含初始的empno的块在哪里? 
    中间的包含i值的那些块在哪里?
    block buffer cache? 
    undo? 
    data block?如果此时B去读, 读的是什么?
    提交后, B再去读, 又读的是什么? 假设另一种情况, B中执行的是一个时间较长的事务, 它跨越了整个A的更新和提交
    情况又是怎样的?
      

  10.   

    那么包含初始的empno的块在哪里?  
    也就是事务开始前的值,在UNDO里。中间的包含i值的那些块在哪里?     
    buffer cache或datafile的数据块里。如果此时B去读, 读的是什么?      
    如果是读到被A修改的块,则在undo里读出。提交后, B再去读, 又读的是什么?
    这个要看COMMIT后多久B去读。以及COMMIT后B是否是第一个去读的。因为可能有delayed block cleanout发生。根据情况不同,B可能还是先读UNDO,发现该事务状态为commited,于是不再用UNDO中数据。然后如果数据还在buffer cache中,则直接从buffer cache中读。否则把datafile中数据块读到buffer cache中,同时进行delayed block cleanout。
    另外如果已有block cleanout,同时已写入datafile,则不读UNDO,直接datafile到buffer cache.今天没时间了。空了的话可以dump block看看,一目了然。LZ可以自己先试试。
      

  11.   

    仔细想了下刚才的问题, 我觉得分岐的原因在于我们对
    “未commit的数据 是否也能从undo里面读到呢?  不能”
    中未commit的数据理解不同.在下面语句中
    update emp set empno = 5 where empno = 3;
    commit;我认为5是未提交的, 提交后应是3
    而vc555和linzhangs认为3未提交, 而5是上一次事务已提交过的
    在数据库具体的原理上, 并没有分岐. 
    当然oracle不能实现read uncommitted级别, 事务隔离这点我说错了楼主可以结贴了
      

  12.   

    还有一点,UNDO数据有一定的保存时间的。 
    好像是undo retention吧
    如果强行限制,则可保证UNDO一直存在。
      

  13.   


    只能读到自己的UNDO,不能读到别人的
      

  14.   

    感觉牵扯了以下几个问题,数据的读写区域:数据缓冲区(Data  buffer)是Oracle 中用于数据块缓冲的区域,数据库常规情况下读写(非直接读写)数据块,undo块等
    ,都会经过这个缓冲区,并适当地保存在缓冲区.如果下次请求同样的块,则不需要从磁盘获得,大大提高了系统的响应速度.commit 做了什么:
    commit 之前,你修改的只是内存里的数据,commit是将你对内存所做的 
    修改存入数据库里面。( rollback是将从上次commit以来所做的修改全部抹掉。下次commit也 
    不会将这些修改存入数据库了。)
    注意,commit后不是说把数据马上写入磁盘,而只是说写入数据库。
        Oracle 使用快速提交机制,当用户发出COMMIT语句时,一个COMMIT记录立即放入联机日志文件,但对应的数据缓冲区的数据块
    的改变,也就是所谓脏数据,一直要等满足条件才会被DBWn写入数据文件.DBWR是干什么的DBWR其实就是 Database Writer n,如果只有一个,那么n 就是0,即进程为DBW0.它是oracle数据库中一个及其重要的
    后台进程,主要负责将数据缓冲区内的数据写入数据文件.其原理很简单,仅仅就是写数据缓冲区内的脏数据,也就是将脏列表
    (Dirty List)上的数据定期写入数据文件,和任何前台用户进程几乎没有什么关系,也不受他们的控制.
    DBWn工作的主要条件如下:
    1>DBWR超时,大约3秒
    2>系统中没有多余的缓冲区来存放数据
    3>CKPT进程出发DBWn
    undo是作什么的
    从Oracle 9iR1开始,Oracle采用了自动Undo管理(AUM),要启动这个功能,必须在init.ora或者spfile.ora中
    设置 undo_management = auto参数,而且从Oralce 9i开始,该参数默认就是auto.
    于此相关的其它参数还有 :
    SQL>show parameter undo
    NAME                       TYPE              VALUE
    undo_management          string              AUTO
    undo_retention           interger            10800
    undo_suppress_errors     Boolean             FALSE
    undo_tablespace          string              UNDOTBS
    除了确保以上参数中的 undo_management=auto外,还要注意另外一个参数undo_retention=n(秒)
    这个参数决定了Undo 最多的保存时间,值越大,就需要越多的Undo空间的支持。
    在oracle 9i中,这部分Undo信息能否保存这么长的时间,我们是没有权限控制的。如果Undo空间很紧张
    的话,Oracle可能提前覆盖Undo信息。以上说明了flashback query的原理,也就是oracle根据Undo 信息,利用undo数据,类似一致性读的方法
    ,可以把表置于一个删除前的时间点(或者是SCN),从而方便用户找回数据。
    从Oracle 10g开始,提供了一个新的命令,可以保证Undo信息在undo_retention的时间内不备覆盖:
    SQL>alter tablespace undotbs1 retention guarantee;