zoukankan      html  css  js  c++  java
  • 14.3.2.3 Consistent Nonlocking Reads 一致性非锁定读

    14.3.2.3 Consistent Nonlocking Reads  一致性非锁定读
    
    一致性读 意味着 InnoDB 使用多版本来保护查询一个数据库在当前时间点的快照。
    
    
    
    查询看到被事务做出的修改, 在那个时间点之前提交的, 随后没有改变或者没有提交事务。
    
    
    例外是查询看到了在同一个会话里的更早的语句的修改。。
    
    
    这个例外导致了下面的异常;如果你更新表的一些记录,一个SELECT 看到的更新记录的最新的版本,
    
    
    但是也看到了老版本的记录。如果其他会话同时更新相同的表,异常意味着你会按到数据库中从未出现的表的
    
    状态。
    
    
    
    如果事务隔离是REPEATABLE READ(默认级别),所有的一致性读在相同的事务读取之前第一个read 创建的快照
    
    
    你可以得到一个更加新鲜的快照 对于你的查询,通过提交当前的事务,在执行新的查询:
    
    
    在READ COMMITED 隔离级别下,每个一致性读读取它自己的新鲜的快照
    
    
    
    一致性读 是默认的模式InnoDB 处理SELECT 语句在READ COMMITTED and REPEATABLE READ 隔离级别。
    
    
    一个一致性读 不设置任何锁在它访问的表上,因此其他会话是自由的修改那些表在相同的时间段
    
    
    假设 你运行在默认的隔离级别REPEATABLE READ。
    
    
    当你执行一个执行读(即,一个普通的SELECT 语句)
    
    
    InnoDB 给你的额事务一个时间点根据 你查询看到的数据库
    
    
    如果另外的事务删除一个记录 并且在你的这个时间点后提交,你不会看到已经删除的记录,更新也是同样对待
    
    。
    
    注意:
    
    
    
    
    数据库状态的快照应用于SELECT 语句,对于DML语句不需要。
    
    
    如果你插入或者修改一些记录,然后提交这个事务,一个DELETE 或者UPDATE 语句从另外一个并发的
    
    REPEATABLE READ 事务可能影响那些刚刚提交的行,尽管会话不能查询它们。
    
    
    如果一个事务Update或者delete 记录被不同的事务提交,那些改变变的可见 低于当前事务。
    
    
    
    测试:
    
    
    Session 1:
    
    mysql> select * from t1;
    +-----+------+------+
    | sn  | id   | info |
    +-----+------+------+
    | 235 |    1 | a1   |
    | 236 |    2 | a2   |
    | 237 |    3 | a3   |
    | 238 |    4 | a4   |
    | 239 |    5 | a5   |
    | 240 |    6 | a6   |
    | 241 |    7 | a7   |
    | 242 |    8 | a8   |
    | 243 |    9 | a9   |
    | 244 |   10 | a10  |
    | 245 |   15 | a15  |
    +-----+------+------+
    11 rows in set (0.00 sec)
    
    
    Session 2:
    
    [root@wx03 ~]# cat t1.pl 
    #!/usr/bin/perl   
    use DBI;  
    $db_name='scan';  
    $ip='127.0.0.1';  
    $user="root";  
    $passwd="1234567";  
    
    $dbh = DBI->connect("dbi:mysql:database=$db_name;host=$ip;port=3306",$user,$passwd,{  
                              RaiseError => 1,  
                              AutoCommit => 0  
                            }) or die "can't connect to database ". DBI-errstr;  
    eval{  
    $dbh->do("delete from t1 where id=1") ;   
    $dbh->commit();};  
    if( $@ ) {  
        warn "Database error: $DBI::errstr
    ";  
                 $dbh->rollback(); #just die if rollback is failing   
                 };  
                         $dbh->disconnect;
    [root@wx03 ~]# perl t1.pl 
    
    
    Session 1:
    
    mysql> delete from t1 where id=1;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> select * from t1;
    +-----+------+------+
    | sn  | id   | info |
    +-----+------+------+
    | 235 |    1 | a1   |
    | 236 |    2 | a2   |
    | 237 |    3 | a3   |
    | 238 |    4 | a4   |
    | 239 |    5 | a5   |
    | 240 |    6 | a6   |
    | 241 |    7 | a7   |
    | 242 |    8 | a8   |
    | 243 |    9 | a9   |
    | 244 |   10 | a10  |
    | 245 |   15 | a15  |
    +-----+------+------+
    11 rows in set (0.01 sec)
    
    
    
    mysql> rollback;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> select * from t1;
    +-----+------+------+
    | sn  | id   | info |
    +-----+------+------+
    | 236 |    2 | a2   |
    | 237 |    3 | a3   |
    | 238 |    4 | a4   |
    | 239 |    5 | a5   |
    | 240 |    6 | a6   |
    | 241 |    7 | a7   |
    | 242 |    8 | a8   |
    | 243 |    9 | a9   |
    | 244 |   10 | a10  |
    | 245 |   15 | a15  |
    +-----+------+------+
    10 rows in set (0.00 sec)
    
    
    
    rollback 结束一个事务,开启一个新的事务
    
    
    
    mysql> commit;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> select * from t1;
    +-----+------+------+
    | sn  | id   | info |
    +-----+------+------+
    | 237 |    3 | a3   |
    | 238 |    4 | a4   |
    | 239 |    5 | a5   |
    | 240 |    6 | a6   |
    | 241 |    7 | a7   |
    | 242 |    8 | a8   |
    | 243 |    9 | a9   |
    | 244 |   10 | a10  |
    | 245 |   15 | a15  |
    +-----+------+------+
    9 rows in set (0.00 sec)
    
    
    commit 结束一个事务,开启新的事务
    
    
    
    
    
    
    
    Session 1:
    mysql> select * from t1;
    +-----+------+------+
    | sn  | id   | info |
    +-----+------+------+
    | 237 |    3 | a3   |
    | 238 |    4 | a4   |
    | 239 |    5 | a5   |
    | 240 |    6 | a6   |
    | 241 |    7 | a7   |
    | 242 |    8 | a8   |
    | 243 |    9 | a9   |
    | 244 |   10 | a10  |
    | 245 |   15 | a15  |
    +-----+------+------+
    9 rows in set (0.00 sec)
    
    
    Session 2:
    
    插入一条ID=99的记录
    
    
    
    Session 1:
    
    mysql> delete from t1 where id=99;
    Query OK, 1 row affected (0.00 sec)
    
    mysql> commit;
    Query OK, 0 rows affected (0.01 sec)
    
    
    你可以提高你的时间点通过提交你的事务, 然后做另外一个SELECT 或者 START TRANSACTION WITH 
    
    CONSISTENT SNAPSHOT.
    这被称为多版本并发控制
    
    
         Session A              Session B
    
               SET autocommit=0;      SET autocommit=0;
    time
    |          SELECT * FROM t;
    |          empty set
    |                                 INSERT INTO t VALUES (1, 2);
    |
    v          SELECT * FROM t;
               empty set
                                      COMMIT;
    
               SELECT * FROM t;
               empty set
    
               COMMIT;
    
               SELECT * FROM t;
               ---------------------
               |    1    |    2    |
               ---------------------
    
    
    
    
    如果你像看到最新鲜的数据库状态,使用READ COMMITTED isolation level 或者locking read:
    
    
    
    SELECT * FROM t LOCK IN SHARE MODE;
    
    
    
    
    Session 1:
    mysql> SELECT * FROM t1 LOCK IN SHARE MODE;
    +-----+------+------+
    | sn  | id   | info |
    +-----+------+------+
    | 237 |    3 | a3   |
    | 238 |    4 | a4   |
    | 239 |    5 | a5   |
    | 240 |    6 | a6   |
    | 241 |    7 | a7   |
    | 242 |    8 | a8   |
    | 243 |    9 | a9   |
    | 244 |   10 | a10  |
    | 245 |   15 | a15  |
    +-----+------+------+
    9 rows in set (0.00 sec)
    
    
    Session 2:
    
    
    mysql> insert into t1(id,info) values(20,'a20'); --Hang
    
    
    
    在
    READ COMMITTED 隔离级别下,每个一致性读读取它自己最新的快照。
    
    
    
    
    Session 1:
    mysql> select * from t1;
    +-----+------+------+
    | sn  | id   | info |
    +-----+------+------+
    | 237 |    3 | a3   |
    | 238 |    4 | a4   |
    | 239 |    5 | a5   |
    | 240 |    6 | a6   |
    | 241 |    7 | a7   |
    | 242 |    8 | a8   |
    | 243 |    9 | a9   |
    | 244 |   10 | a10  |
    | 245 |   15 | a15  |
    | 247 |   20 | a20  |
    +-----+------+------+
    10 rows in set (0.00 sec)
    
    mysql> insert into t1(id,info) values(25,'a25');
    Query OK, 1 row affected (22.22 sec)
    
    
    事务没有提交
    
    
    
    Session 2:
    
    mysql> SELECT * FROM t1 LOCK IN SHARE MODE;--Hang
    
    
    
    在LOCK IN S HARE 模式下,一个locking read 发生。
    
    一个SELECT 堵塞直到事务包含最新鲜的记录
    
    
    一致性读不工作在某些DDL 语句:
    
    1. 一致性读在DROP TABLE 不工作,因为MySQL 不能使用一个表已经被删除和InnoDB 摧毁这个表
    
    
    关闭自动提交:
    
    Session 1:
    
    mysql> select * from t5;
    +----+------+------+
    | sn | id   | info |
    +----+------+------+
    |  1 |    1 | a1   |
    |  2 |    5 | a5   |
    |  3 |   10 | a10  |
    |  4 |   15 | a15  |
    |  5 |   20 | a20  |
    |  6 |   25 | a25  |
    |  7 |   30 | a30  |
    |  8 |   35 | a35  |
    |  9 |   40 | a40  |
    | 10 |    2 | a2   |
    +----+------+------+
    10 rows in set (0.00 sec)
    
    
    Session 2:
    
    mysql> drop table t5; --hang
    
    
    select 会堵塞DDL操作
    
    
    一致读不能在ALTER TABLE时工作, 因为语句做了一个原表的临时拷贝,删除原始表 当临时copy 被创建。
    
    
    当你重新发起一个一致性读 在一个事务内, 表里的记录是不可见的 因为那些记录不存在
    
    当事务的快照被创建时

  • 相关阅读:
    使goroutine同步的方法总结
    PHP类自动加载技术
    swoole架构分析
    网站用户行为分析——HBase的安装与配置
    Java基础——异常处理
    大数据技术原理与应用——分布式文件系统HDFS
    大数据技术原理与应用——大数据处理架构Hadoop
    廖老师的Python教程——安装Python
    廖老师的Python教程——Python简介
    大数据技术原理与应用——大数据概述
  • 原文地址:https://www.cnblogs.com/zhaoyangjian724/p/6199850.html
Copyright © 2011-2022 走看看