数据库事务并发问题:脏读,不可重复读,幻读

脏读

脏读是两个并发的事务1和事务2在执行时,事务1读取了事务2尚未提交的数据,而事务2由于出现异常回滚了,事务1拿着读到的事务2的数据进行后续操作时就出现数据错误了,脏读了。如下图:

 

不可重复读

事务1中读取了某个数据,同时事务2也在修改这个数据,在事务2修改完这个数据并提交事务后,事务1又一次读取了这个数据,两次读取的同一数据就会不一致,这种现象叫做不可重复读。如图所示:

幻读

事务1中首先读取了某一业务(比如交易记录数)记录数,此时并发的事务2新增了一条交易记录,并提交事务,此时事务1再次读取交易记录数时,记录数前后就会出现不一致,这种现象称为幻读。如图所示:

事务隔离级别

事务隔离级别的设置能部分规避上述出现的3个问题,下面看下spring中事务隔离级别的配置。

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {

    @AliasFor("transactionManager")
    String value() default "";

    @AliasFor("value")
    String transactionManager() default "";

    Propagation propagation() default Propagation.REQUIRED;

    Isolation isolation() default Isolation.DEFAULT;

    int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

    boolean readOnly() default false;

    Class<? extends Throwable>[] rollbackFor() default {};

    String[] rollbackForClassName() default {};

    Class<? extends Throwable>[] noRollbackFor() default {};

    String[] noRollbackForClassName() default {};

}
package org.springframework.transaction.annotation;

import org.springframework.transaction.TransactionDefinition;

public enum Isolation {
    //使用所连接数据库的默认隔离级别(比如mysql默认是REPEATABLE_READ)。
    DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),
    //未提交读
    READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
    //已提交读
    READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),
  //可重复读
    REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),
  //串行化
    SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);


    private final int value;


    Isolation(int value) {
        this.value = value;
    }

    public int value() {
        return this.value;
    }

}

事务隔离级别与可能出现的并发事务问题的关系如下:

 

posted @ 2020-11-15 21:12  一首简单的歌  阅读(290)  评论(0编辑  收藏  举报