客户端并发访问数据库时,数据库中的相同数据可能同时被多个事务访问,如果没有采取必要的隔离措施,就会导致并发问题,破坏数据的完整性。问题归为5类,3类数据读问题以及2类数据更新问题:
1. 脏读
A事务读取B事务尚未提交的更改数据,并在这个数据的基础上操作。如果恰巧B事务回滚,那么A事务读到的数据根本是不被承认的。
2. 不可重复读
A事务读取了B事务已经提交的更改数据。假设A在取款事务的过程中,B往该账户转账100元,A两次读取的账户的余额发生了不一致。
3. 幻读 :
A事务读取B事务提交的新增数据,这时A事务将出现幻想读的问题。幻想读一般发生在计算统计数据的事务中,假设银行系统在同一事务中,两次统计账户总金额,在两次统计过程中,刚好新增了一个存款账户,并存入了100元,这时两次统计金额不一致。
4.第一类丢失更新
A事务撤销时,把已经提交的B事务的更新数据覆盖掉。
5.第二类丢失更新
A事务覆盖B事务已经提交的数据,造成B事务所操作丢失。
事务隔离级别对并发问题的解决情况
隔离级别 | 脏读 | 不可重复读 | 幻象读 | 第一类丢失更新 | 第二类丢失更新 |
---|
Read uncommitted | 允许 | 允许 | 允许 | 不允许 | 允许 |
Read committed | 不允许 | 允许 | 允许 | 不允许 | 允许 |
Repeatable read | 不允许 | 不允许 | 允许 | 不允许 | 不允许 |
Serializable | 不允许 | 不允许 | 不允许 | 不允许 | 不允许 |
事务传播行为
事务传播行为类型 | 说明 |
---|
PROPAGATION_REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在事务,就加到这个事务中。这是最常见的选择。 |
PROPAGATION_SUPPORTS | 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。 |
PROPAGATION_MANDATORY | 使用当前事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NEW | 新建事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起 |
PROPAGATION_NEVER | 以非事务的方式执行,如果当前存在事务,则抛出异常 |
PROPAGATION_NESTED | 如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行 |