`
gtbald
  • 浏览: 20173 次
文章分类
社区版块
存档分类
最新评论

事务的隔离级别和幻读问题

阅读更多

 

事务的隔离级别,是一个很基本的概念,从自己的角度整理一下.

 

分为两部分,一个是事务.一个是隔离级别.

 

第一个:事务

ACID是指在可靠数据库管理系统(DBMS)中,事务(transaction)所应该具有的四个特性:

原子性(Atomicity)

一致性(Consistency)

隔离性(Isolation)

持久性(Durability)

 

一个用户的操作可能要修改两张数据表,这个操作对应程序中的方法.以下是示例代码,没有真实意义,只是为了说明.

 

  /**
     * 更新项目的站点,示例代码没有意义
     * @param pid 项目ID
     * @param lid 站点ID
     * @return
     */
    public String updateProject(Integer projectId,Integer siteId){
        projectDAO.updateProjectLogicSite(projectId, siteId);
        siteDAO.addProject(projectId, siteId);
    }

 如果下面的站点加入项目失败

siteDAO.addProject(projectId, siteId);   //失败,DB中没有生效

但是下面的代码生效了

projectDAO.updateProjectLogicSite(projectId, siteId);//这个DB中生效了

 

因为上面的两句代码是两个事务了.使这个方法整体作为一个事务,(spring事务管理,使用注释方式)

/**
     * 更新项目的站点
     * @param pid 项目ID
     * @param lid 站点ID
     * @return
     */
    @Transactional(isolation=Isolation.REPEATABLE_READ)
    public String updateProject(Integer pid,Integer lid){
        projectDAO.updateProjectLogicSite(pid, lid);
        siteDAO.addProject(pid, lid);
    }

 那么,第二个更新站点失败,第一个更新项目也会一起回滚.

具体可以参考spring,和db的事务概率.

 

第二个 隔离级别

那么使用哪个隔离级别呢?

Spring提供了五个可选参数,对应了事务的四个隔离级别(怎么5个对应4个呢?看了就知道)

@Transactional(isolation=Isolation.DEFAULT)  //默认使用DB的隔离级别,如果是mysql的innodb默认是REPEATABLE_READ
@Transactional(isolation=Isolation.READ_UNCOMMITTED)
@Transactional(isolation=Isolation.READ_COMMITTED)
@Transactional(isolation=Isolation.REPEATABLE_READ)
@Transactional(isolation=Isolation.SERIALIZABLE)

 每个隔离级别的意思和介绍很多书和文章都讲解的很好,我就不重复了,下面按我自己的思路理一下

 

假设有TA和TB两个方法.都假设一个方法中有两个或者多个DB操作.

从两方面来说明.

A.是否阻塞其他事务往下执行

 

   1.TA是读操作先执行   TB是读操作后执行  无论两个方法的隔离级别是什么都不影响.

   2.TA是读操作先执行   TB是写操作后执行 只有TA是SERIALIZABLE才会被阻塞.其他时候都不会被阻塞.

   3.TA是写操作先执行   TB是读操作后执行  只有TB是SERIALIZABLE才会被阻塞.其他时候都不会被阻塞.

   4.TA是写操作先执行   TB是写操作后执行  只有TA没有事务,TB不会被阻塞,其他时候都要等TA操作完成.

 

注意(第4点,这里更严格的表示应该是TA的这个方法没有执行完,TB会被阻塞,方法没有声明为一个事务的时候TA一个DB操作就是一个事务,这个DB操作的时候,是会阻塞TA的写操作的)

 

B.读到的数据

首先假设一个场景是,TA是读操作先执行  然后TB是写操作,TA再次读取读到的是什么.其实只有这一个场景有问题,其他时候都是正常的操作.或者说TA先写,TB读,这个时候其实是第一个场景的后半部分.下面来列出什么情况读到什么.

TA1和TA2是TA这个方法中的两个读方法

1.TA没有事务   无论TB这个事务是否提交 TA2读到的都是TB写的数据.(更新丢失)

2.TA有事务,隔离级别READ_UNCOMMITTED  无论TB是否提交 TA2读到的都是TB写的数据  (和上面的区别是没有第一中更新丢失,但是TB回滚TA2会脏读)

3.TA有事务,隔离级别READ_COMMITTED  TA2读到的都是TB事务提交后的数据,没有提交读不到.(没有脏读,TA1读和TA2读到的不一致)

4.TA有事务 隔离级别REPEATABLE_READ   TA2读到的数据和TA1一样无论TB是否有提交(所以可以重复读,这里有幻读的问题,下面专门介绍幻读)

5.TA有事务 隔离级别SERIALIZABLE  TA2读到的和TA1一样,幻读都没有,看阻隔就知道,有写的时候都是排队来的.

幻读

专门理一下幻读,幻读发生在读一张表中不同行的数据时.

比如TA1读操作  select * from project where create_date > '20100101' 第一次查询有2条记录.

TB写操作     插入一条记录创建时间大于20100101的记录

TA2 再读 就读出3条记录了,这个时候就幻读了.

因为REPEATABLE_READ的时候TB是可以同时写的就有这个问题.

SERIALIZABLE是排队的,TB只有在TA的两次读操作都完成后才可以写,所以是完全没有问题的.

 

幻读导致的问题1

比如注册用户,希望用户名不重名.

TA和TB要注册用户gtbald.

TA1查询不存在gtbald.

TB1查询不存在gtbald.

TA2插入gtbald

TB2插入gtblad.

有两个gtbald了.

目前我知道的解决办法可以是DB用户名加上唯一索引.或者业务中注册事务隔离级别设为SERIALIZABLE(性能差).

 

幻读导致的问题2

比如报名人数限制为100人

TA和TB都要提交报名人

TA1查询总报名人数99人

TB1查询总报名人数99人

TA2增加报名一人 现在总报名人数100人

TB2增加报名一人  现在总报名人数101人

 

目前我知道的解决办法:报名务隔离级别设为SERIALIZABLE(性能差).

接下来研究幻读问题的解决方案.

分享到:
评论

相关推荐

    MySQL事务隔离级别

    MySQL默认的事务隔离级别是可重复读,它能防止脏读和不可重复读。在这个级别下,事务在整个事务期间可以看到一致的数据视图,即同一查询始终返回相同的结果,除非事务自己对数据进行了修改。然而,幻读问题依然存在...

    MySQL的四种事务隔离级别

    MySQL数据库管理系统提供了四种事务隔离级别来处理事务并发中可能遇到的问题。事务并发问题通常包括脏读、不可重复读和幻读。 一、事务的基本要素(ACID) 事务具有四个基本要素,即原子性(Atomicity)、一致性...

    spring常用数据库事务传播属性和事务隔离级别1

    3. **Isolation.READ_COMMITTED**:每个事务只能读取已经提交的数据,避免了脏读,但可能遇到不可重复读和幻读问题。Oracle 数据库默认使用此级别。 4. **Isolation.REPEATABLE_READ**:防止了脏读和不可重复读,但...

    spring事务的传播特性和事务隔离级别

    ### Spring事务的传播特性和事务隔离级别 #### 一、Spring事务的传播特性(Propagation) 在Spring框架中,事务管理不仅提供了ACID属性的支持,还引入了事务的传播特性,这些特性决定了当一个方法调用另一个方法时,...

    SQLserver锁和事务隔离级别的比较与使用

    SQL Server的锁机制和事务隔离级别是数据库管理系统中确保数据一致性、避免并发问题的重要机制。在SQL Server中,锁主要用于控制多个用户同时访问同一数据时的并发操作,而事务隔离级别则是确定在事务中如何处理这些...

    SPRING事务传播特性&事务隔离级别

    ### Spring 事务传播特性和事务隔离级别详解 #### 一、Spring 事务传播特性 在进行多层服务架构设计时,事务的管理尤其重要。为了确保数据的一致性,Spring 提供了一种灵活的方式来控制事务的传播行为。下面详细...

    06-VIP-深入理解Mysql事务隔离级别与锁机制.pdf

    在并发事务处理过程中,可能会出现更新丢失、脏读、不可重复读和幻读等问题。这些问题都是由于多事务并发执行引起的,需要通过事务隔离机制和锁机制来解决。 事务隔离级别 数据库的事务隔离级别是用来解决读一致性...

    4种事务的隔离级别

    在SQL92标准中,定义了四种事务隔离级别,分别是读未提交(Read Uncommitted)、读提交(Read Committed,简称RC)、可重复读(Repeated Read,简称RR)以及串行化(Serializable)。InnoDB存储引擎实现了这四种隔离...

    怎么理解SQL SERVER中事务隔离级别及相应封锁机制.pdf

    理解SQL Server中事务隔离级别及相应封锁机制 SQL Server中事务隔离级别是数据库管理系统中一个重要的概念,它决定了事务之间的并发执行和数据的一致性。本文将详细介绍SQL Server中事务隔离级别的概念、分类、特点...

    事务隔离级别 .pdf

    事务隔离级别是控制事务之间交互的方式,以防止诸如脏读、不可重复读和幻读等并发问题。 1. **事务隔离级别的分类** - **读未提交(Read Uncommitted)**: 这是最低的隔离级别,允许一个事务看到其他事务尚未提交...

    事务隔离级别 .docx

    事务隔离级别定义了在一个事务内的修改在其他事务中何时可见,以及如何处理并发操作可能引发的问题。 1. **读未提交(Read Uncommitted)** 在这个最低的隔离级别,一个事务可以读取到其他事务未提交的数据,这...

    52 MySQL是如何支持4种事务隔离级别的?Spring事务注解是如何设置的?l.pdf

    每种隔离级别对应不同程度的事务并发问题的防范,其中,MySQL 默认的事务隔离级别是 REPEATABLE READ。 REPEATABLE READ 隔离级别在 MySQL 中具有一个显著的特性,即它通过多版本并发控制(MVCC,Multi-Version ...

    数据库事务隔离级别.docx

    数据库事务隔离级别是用来管理多个事务之间相互影响的程度,主要解决的问题包括脏读、不可重复读、幻读等。 #### 二、事务隔离级别的定义与作用 事务隔离级别是指数据库系统为每个事务提供的一种环境,以确保事务在...

    mysql事务隔离级别1

    MySQL中的事务隔离级别是数据库管理系统确保事务之间相互独立的重要机制,它主要针对并发操作时可能出现的问题,如脏读、不可重复读和幻读等。在MySQL的InnoDB存储引擎中,有四种不同的事务隔离级别: 1. **读未...

    spring 事务传播与隔离级别DEMO

    本DEMO主要探讨的是Spring事务的传播行为和隔离级别,这些概念对于理解和优化数据库操作至关重要。让我们深入理解这些概念及其实际应用。 首先,我们来谈谈事务的传播行为。在Spring中,当一个方法被另一个具有事务...

    JDBC事务 JTA事务 传播特性 隔离级别

    - **序列化(Serializable)**:最高的隔离级别,完全避免了脏读、不可重复读和幻读,但可能影响性能。 4. **持久性(Durability)**:一旦事务提交,其更改就会永久保存,即使系统出现故障也能恢复。 接下来,...

    深入理解Mysql事务隔离级别与锁机制.pdf

    事务隔离级别是数据库系统中的一种机制,用于解决多事务并发问题,使得事务之间的执行不受影响。这种机制可以分为四个级别:Read Uncommitted、Read Committed、Repeatable Read、Serializable。每个级别都有其特点...

    02.Spring支持的常用数据库事务传播属性和事务隔离级别.zip

    事务隔离级别是控制并发操作时如何避免脏读、不可重复读和幻读的关键。Spring支持四种标准的SQL事务隔离级别: 1. READ_UNCOMMITTED(未提交读):最低级别的隔离,可能会出现脏读、不可重复读和幻读。在大多数情况...

Global site tag (gtag.js) - Google Analytics