zoukankan      html  css  js  c++  java
  • MySQL InnoDB MVCC 能否完全解决幻读?

    幻读是指多事务并发中一个事务读到了另一个事务insert的记录。

    在REPEATABLE READ隔离级别下,假设事务T1执行后,事务T2开始执行,并新增一条记录,然后事务T2提交,这时在事务T1中执行select是看不到事务T2新增的这条记录的。因为在事务T1生成readview的时刻,事务T2属于未来事务,所以是看不到事务T2新增的这条记录的。

    假设有如下场景:

    # 表结构如下
    CREATE TABLE hero (
        number INT,
        name VARCHAR(100),
        country varchar(100),
        PRIMARY KEY (number),
        KEY idx_name (name)
    ) Engine=InnoDB CHARSET=utf8;
    
    # 事务T1,REPEATABLE READ隔离级别下
    mysql> BEGIN;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SELECT * FROM hero WHERE number = 30;
    Empty set (0.01 sec)
    
    # 此时事务T2执行了:INSERT INTO hero VALUES(30, 'g关羽', '魏'); 并提交
    
    mysql> UPDATE hero SET country = '蜀' WHERE number = 30;
    Query OK, 1 row affected (0.01 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> SELECT * FROM hero WHERE number = 30;
    +--------+---------+---------+
    | number | name    | country |
    +--------+---------+---------+
    |     30 | g关羽   | 蜀      |
    +--------+---------+---------+
    1 row in set (0.01 sec)
    

    在REPEATABLE READ隔离级别下,T1第一次执行普通的SELECT语句时生成了一个ReadView,之后T2向hero表中新插入了一条记录便提交了,ReadView并不能阻止T1执行UPDATE或者DELETE语句来对改动这个新插入的记录(因为T2已经提交,改动该记录并不会造成阻塞),但是这样一来这条新记录的trx_id隐藏列就变成了T1的事务id,之后T1中再使用普通的SELECT语句去查询这条记录时就可以看到这条记录了,也就把这条记录返回给客户端了。因为这个特殊现象的存在,你也可以认为InnoDB中的MVCC并不能完完全全的禁止幻读。

  • 相关阅读:
    multiview
    RadioButton
    信息存储与管理读书笔记1
    个人Wordpress站点设置Windows Live writer
    test
    test
    AS类库推荐
    JAVA坏境变量中的JAVA_HOME path classpath 的设置与作用
    actionscript3 中关于sprite的mask问题
    RED5遍历客户端并生成在线列表[转]
  • 原文地址:https://www.cnblogs.com/jmliao/p/13154622.html
Copyright © 2011-2022 走看看