zoukankan      html  css  js  c++  java
  • constant read 和 current read

    来自网络,并且在本机实验完成:

    onsistent read :
    我的理解,就是通过scn来读取。  读取的过程中要保证 scn是一致的。举个例子,一个SELECT 语句在SCN=100的时刻开始读取一系列数据块。在执行的过程中,他发现一个数据块的SCN变成了101,也就是说这个数据块被更改过了。那么SELECT 就不去读取这个数据块了,而是去读取它的一个早期版本 ,scn=100的这个版本。 这个版本应该在undo空间中。这就是CONSISTENT read。  这也许让你想到了 oracle的写不影响读 这个机制。 比如一个让update 了一条记录, 只要他没commit, 另一个让在读取这条记录的时候就总是读取原来的值。但实际上,即使那条更改被commit了, 只要你的select 时间点,或者说scn 早于commit,你看到的仍然是之前commit之前的,也就是你提交select那个时间点的记录。接下来的第一条例子,就可以证明这一点。

    做一个实验,证明上面的consistent read
    1. 现在有表,内容如下
    1. SQL> select id ,v1,DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) from t1;
    2.         ID V1                       DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
    3. ---------- ------------------------ ------------------------------------
    4.          1 a                                                       68194
    5.          2 b                                                       68195
    复制代码
    2. 在session 1 中运行下列语句
    1. 11:34:51 SQL> select v1 from t1 where id=2 and v1='b' and (select count(*) from dba_objects , dba_tables )>1;
    2. V1
    3. ------------------------
    4. b
    5. Elapsed: 00:00:31.11
    复制代码


    注意,这个语句运行了约办分钟,所以我们有充足的时间在这条语句运行完毕之前,执行第三步,





    3. 第三步执行了一个update,把id=2,v1='b' 这条记录修改了,并且做了commit。
    1. SQL> update t1 set v1='M' where id=2 ;
    2. 1 row updated.
    3. Elapsed: 00:00:00.01
    4. SQL> commit;
    5. Commit complete.
    6. Elapsed: 00:00:00.02
    复制代码
    第三步执行完,第二步才返回结果。我们可以看到,虽然第三步commit了,但是第二步没有返回最新的结果。第二步返回的是 其开始时刻 scn的结果。所以,这就是consistent read了。它只根据scn去读取数据块,保证了数据的完整性,即不会被后来的更新所改变。














    current read,读取当前的 data block,最新的 data block,比如在update, delete的时候就总是current read。 因为你要对最新的data block做更改,对过去更改没有任何实际意义。


    下面是我自己的实验过程。
    1. 首先看一下,我的表 id=2这一行的记录。可以看到 id=2 对应着 v1=b
    1. SQL> select id ,v1,DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) from t1;
    2.         ID V1                       DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
    3. ---------- ------------------------ ------------------------------------
    4.          1 a                                                       68194
    5.          2 b                                                       68195
    复制代码
    2. 我们新开一个session,并输入下面的语句
    1. 11:49:06 SQL> update t1 set v1='B' where id=2 and v1='b' and (select count(*) from dba_objects , dba_tables )>1;
    2. 0 rows updated.
    3. Elapsed: 00:01:41.14
    复制代码
    这个SQL执行了一分钟的时间,因为后面的(select count(*) from dba_objects,dba_tables)这个条件非常的耗时。在输入了这条语句,并且该语句运行完之前,我们来做第三步

    3.打开第二个session,输入下面的语句
    1. SQL> update t1 set v1='M' where id=2;
    2. 1 row updated.
    3. Elapsed: 00:00:00.01
    4. SQL> commit;
    复制代码
    因为,第二步要执行一分钟,所以我们有充足的时间在第二步完成之前完成第三步。可以看到,第三步完成后,第二步才返回结果--更新了0行。
    整个的执行过程可以这样描述,
    session 1 开始了一个update 操作,他通过consistent read(id= 2 , v1='b') 获取了数据块的id。
    session 2 修改了 id=2 这一行的数据,变成了id=2,v1=‘M'
    session 1 通过一个通过最开始拿到的block id去以current read读取数据块,结果发现数据块不符合filter的条件了 id=2 and v1='b'
    所以 session 1没有更新。
     
    个人理解:
    最终要的就是上面这一段标黄的部分,更新操作并非不遵循读一致性,在更新操作执行查询的那一部分的时候,是遵循读一致性的,只不过在执行更新的时候,做了实时的二次验证罢了。
     
    此时,如果在更新操作执行一半的时候,insert 一条符合更新操作查询部分的数据,这条数据是不会被更新操作更新的。因为更新的内容局限在第一次读一致性那个点上的数据了。只能比它少,不能比它多了。
  • 相关阅读:
    从零搭建Spring Boot脚手架(4):手写Mybatis通用Mapper
    从零搭建Spring Boot脚手架(3):集成mybatis
    从零搭建Spring Boot脚手架(2):增加通用的功能
    从零搭建Spring Boot脚手架(1):开篇以及技术选型
    Hibernate Validator校验参数全攻略
    Spring Data R2DBC响应式操作MySQL
    Spring Security 实战干货:从零手写一个验证码登录
    Spring Security 实战干货:图解用户是如何登录的
    基于.NetCore3.1系列 —— 日志记录之日志核心要素揭秘
    基于.NetCore3.1系列 —— 日志记录之日志配置揭秘
  • 原文地址:https://www.cnblogs.com/xiaolang8762400/p/6928094.html
Copyright © 2011-2022 走看看