事务管理简介

1. 什么是事务

事务,可以简单理解为一件事情,一件有始有终的事情,并且不能半途而废,否则前功尽弃的事情。也就是说,事务必须是一个完整的整体,不能被分割了,已经是最小的单位。因此,事务的第一个特性可以归纳为:原子性(atomicity)
在日常生活中,现在我们经常碰到一件事情就是转账,假如 A 转给他朋友 B 10000 RMB,那么正常表现应该是 A 的账户扣掉 10000 RMB,B 的账户加上 10000 RMB,但是,世界都是脆弱的,何况是网络,什么事情都有可能发送,所以有可能出现 A 的账户扣掉 10000 RMB 了,可是 B 的账户没有加上 10000 RMB ,那 A 的苦恼就来了。所以我们需要数据不会被破坏,即事务的第二个特性:一致性(consistency)
在操作数据库中,现在都是并发操作,因此可能会出现多个用户同时操作一条记录,然而他们的操作类型还不同,这样他们的操作相互影响,有些用户可能操作成功,有些用户操作失败。因此,我们必须保证数据库操作之间是“隔离”的,这就是事务的第三个特性:隔离性(isolation)。在隔离性的特性基础上,数据库专家定义了一个规范,就是事务隔离级别

  • READ_UNCOMMITTED
  • READ_COMMITTED
  • REPEATABLE_READ
  • SERIALIZATION
    事务的最后一个特性就是持久性(durability)
    事务的四个特性简称为 ACID。原子性是基础,隔离性是手段,持久性是目的,真正的老大就是一致性。

2. 事务面临的问题

在事务的 ACID 特性中,最难理解的就是隔离性了,经常容易理不清其中的逻辑。其实隔离性的四个级别只是为了解决数据在高并发下产生的如下三个问题:

  • dirty read(脏读)
  • unrepeatable read(不可重复读)
  • phantom read(幻读)
  • 脏读

顾名思义就是读了错误的数据。

事务 A 读取了事务 B 未提交的数据,并在这个基础上又做了其他操作

时间 事务A(存款) 事务B(取款)
T1 开始事务
T2 开始事务
T3 查询余额(1000 元)
T4 取出 1000 元(余额 0 元)
T5 查询余额(0 元)
T6 撤销事务(余额恢复为 1000 元)
T7 存入 500 元(余额为 500 元)
T8 提交事务

余额应为 1500 元才对,在时间 T5 时,事务 A 此时查询余额为 0 元,这个数据就是脏数据。从这个过程来看,其实就是事务 A 读取了事务 B 未提交的数据,以至于脏读。

  • 不可重复读
    事务 A 读取了事务 B 已提交的更改数据
时间 事务A(存款) 事务B(取款)
T1 开始事务
T2 开始事务
T3 查询余额(1000 元)
T4 查询余额(1000 元)
T5 取出 1000 元(余额 0 元)
T6 提交事务
T7 查询余额(0 元)

事务 A 其实除了查询了两次以外,其他什么事情都没有做,结果钱就从 1000 变成 0 了,这就是不可重复读了,毕竟事务 B 提交了事务,数据库将结果进行持久化,所以事务 A 再次读取时自然就发生了变化。
这种现象基本上是可以理解的,但在有些“变态”的场景下却是不允许的。毕竟这种现象也是事务之间没有隔离所造成的。

  • 幻读

搞不清楚什么原因,数据就变了
事务 A 读取了事务 B 已提交的新增数据

时间 事务A(存款) 事务B(取款)
T1 开始事务
T2 开始事务
T3 统计总存款 10000 元
T4 存入 100 元
T5 提交事务
T6 统计总存款 10100 元

3. spring 事务传播行为

Spring 一共提供了 7 钟事务传播行为,分别是:

  • PROPAGATION_REQUIRED
  • PROPAGATION_REQUIRED_NEW
  • PROPAGATION_NESTED
  • PROPAGATION_SUPPORTS
  • PROPAGATION_NOT_SUPPORTS
  • PROPAGATION_NEVER
  • PROPAGATION_MANDATORY

事务传播可以理解为事务从哪里来要传播到哪里去,spring 解决的是方法之间的事务传播,所以,事务是从方法 A 传播到方法 B。

你可能感兴趣的:(事务管理简介)