zoukankan      html  css  js  c++  java
  • 数据库的脏读、不可重复读和幻读区别

    众所周知MySQL从5.5.8开始,Innodb就是默认的存储引擎,Innodb最大的特点是:支持事务、支持行级锁。 既然支持事务,那么就会有处理并发事务带来的问题:更新丢失、脏读、不可重复读、幻读;相应的为了解决这四个问题, 就产生了事务隔离级别:未提交读(Read uncommitted),已提交读(Read committed),可重复读(Repeatable read),可序列化(Serializable)。

    事务的特性:

    原子性:指处于同一个事务中的多条语句是不可分割的。即它对数据库的修改要么全部执行,要么全部不执行

    一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如转账,转账前两个账户余额之和为2k,转账之后也应该是2K。

    隔离性:指多线程环境下,一个线程中的事务不能被其他线程中的事务打扰 持久性:事务一旦提交,就应该被永久保存起来。

    持久性:事务一旦提交,就应该被永久保存起来。

    1、概念说明:      

    更新丢失:最后的更新覆盖了其他事务之前的更新,而事务之间并不知道,发生更新丢失。更新丢失,可以完全避免,应用对访问的数据加锁即可。   

    脏读(针对未提交的数据):一个事务在更新一条记录,未提交前,第二个事务读到了第一个事务更新后的记录,那么第二个事务就读到了脏数据,会产生对第一个未提交 数据的依赖。一旦第一个事务回滚,那么第二个事务读到的数据,将是错误的脏数据。   

    不可重复读(读取数据本身的对比):一个事务在读取某些数据后的一段时间后,再次读取这个数据,发现其读取出来的数据内容已经发生了改变,就是不可重复读。   

    幻读(读取结果集条数的对比):一个事务按相同的查询条件查询之前检索过的数据,确发现检索出来的结果集条数变多或者减少(由其他事务插入、删除的),类似产生幻觉。

    2、事务隔离级别:   

    并发处理带来的问题中,更新丢失可以完全避免,由应用对数据加锁即可。脏读、不可重读度、幻读,其实都是数据库的一致性问题,必须由一定的事务隔离机制来解决。 其中一种方法是:不用加锁,通过一定的机制生成一个数据请求时间点的一致性快照,并用这个快照来提供一个界别的一致性读取。从用户的角度看,好像是数据库提偶拱了 统一数据的多个版本。这种技术叫做:数据库多版本并发控制,MVCC 多版本数据库。   

    事务隔离的本质是使事务在一定程度上串行化执行,显然和并发机制是矛盾的。数据库的事务隔离越严格,并发负作用越小,代价越高(影响并发访问了呗)。   

    为了解决隔离和并大的矛盾,IOS SQL92规定了4个隔离级别。(隔离==串行)

    大多数数据库默认的事务隔离级别是 Read Committed,比如 SQL Server , Oracle。但 MySQL 的默认隔离级别是 Repeatable Read。

      举例1:

    脏读(Read Uncommitted)
    通俗的讲,一个事务在处理过程中读取了另外一个事务未提交的数据。(你都还没提交,我就读到了你刚操作的数据,万一你回滚了怎么办,你说这脏不脏。)
    举例(事务B未提交,事务A却读到了事务B未提交的数据)

    3.2 不可重复读(Non-repeatable Read)
    通俗的讲,一个事务范围内,多次查询某个数据,却得到不同的结果。
    与脏读的区别:脏读是读到未提交的数据,而不可重复读读到的却是已经提交的数据,但实际上是违反了事务的一致性原则。
    举例(事务B提交后,事务A却读到了事务B已提交的数据,导致事务A两次读到地数据不一致)

    3.3 幻读
    在Repeatable Read隔离级别下,一个事务可能会遇到幻读(Phantom Read)的问题。
    事务A读取与搜索条件相匹配的若干行。事务B以插入或删除行等方式来修改事务A的结果集,然后再提交。
    举例(id主键唯一,事务A搜索id=10的数据,事务A搜索不到id=10的数据,然后事务B新增id=10的数据并提交,事务A更新id=10的数据却成功,插入id=10却失败,现在搜索id=10也有记录)

      举例2:

      1. 脏读的情况:对于两个事务T1与T2,T1读取了已经被T2更新但是还没有提交的字段之后,若此时T2回滚,T1读取的内容就是临时并且无效的

      开启两个mysql客户端,并创建一张测试表transaction

      

      更改默认隔离级别REPEATABLE READ为READ UNCOMMITTED,用于测试

    SELECT @@tx_isolation; #查询隔离级别
    SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; # 更改隔离级别

      

       两个客户端同时开启事务,其中一个事务做UPDATE操作,另一个事务做SELECT

      

      若此时黑色背景的客户端进行回滚,则白色背景的客户端读取的数据就是临时并且无效的。即脏读。

      2. 不可重复读: 对于两个事务T1和T2,T1读取了一个字段,然后T2更新了该字段并提交之后,T1再次提取同一个字段,值便不相等了。

      

      重复读取的结果不一致的情况发生。

      3. 幻读: 对于两个事务T1、T2,T1从表中读取数据,然后T2进行了INSERT操作并提交,当T1'再次读取的时候,结果不一致的情况发生。

      

  • 相关阅读:
    39页第3题 求x的n次幂
    实验4-1 求花费电费的金额
    实验二利用循环计算多个圆柱体体积
    39页第一题 四则运算及其余数
    实验一计算圆的面积
    7-14
    第六章例6-3
    第六章例6-2
    第六章例6-1
    第五章例5-9
  • 原文地址:https://www.cnblogs.com/-mrl/p/13056433.html
Copyright © 2011-2022 走看看