记录一下事务的理解

为什么要有事务?

原子性 → 失败可回滚。
一致性 → 数据状态始终正确
隔离性 → 并发读写不相互干扰(通过加锁/MVCC实现)。
持久性 → 提交后不丢数据(通过redo log、双写缓冲等手段实现)。

一致性和其他 ACID 的关系

原子性:保证部分成功、部分失败不会破坏一致性。

隔离性:防止并发事务互相干扰,导致数据不一致。

持久性:保证提交后的结果不会丢失,否则数据可能不一致。

一致性是最终目标,其他三个是保证手段。

隔离性要解决什么问题?

多个事务并发执行时,读写互不干扰。其中:

  • 保证读不干扰,主要依赖 根据隔离级别确定使用 行级锁(S 锁)或 MVCC (快照)机制。
  • 保证写不干扰,主要依赖 行级锁(X 锁)。

读不干扰,根据不同的适用场景,划分具体的隔离级别,不同的隔离级别体现在:

  • 读未提交 → 不加锁,可读脏数据。
  • 读已提交 → 不加锁,过滤了未提交的数据,避免脏读。
  • 可重复读 → 使用MVCC机制(快照读),避免不可重复读。
  • 串行化 → 加 S 锁(当前读)+ 间隙锁,可以避免幻读。

注:

  1. S 锁:允许事务 读取一行数据,但 不允许修改。其他事务也可以加 S 锁(共享读取)。
  2. X 锁:允许事务 修改一行数据,同时阻止其他事务对该行加任何类型的锁(S 或 X)。
  3. 串行化隔离级别下,普通 SELECT 会被隐式转换成 SELECT ... LOCK IN SHARE MODE。
  4. 在 InnoDB 中,如果一个事务已经对某行加了 S 锁,它 可以尝试升级成 X 锁,比如通过 UPDATE 或 SELECT … FOR UPDATE,这叫 锁升级。但成功升级的前提是 没有其他事务持有 S 锁或 X 锁,否则会阻塞,直到其他事务释放锁(或触发死锁检测机制回滚其中一个事务)。
  5. SELECT 语句默认是快照读,而 LOCK IN SHARE MODE 与 FOR UPDATE 都是当前读。LOCK IN SHARE MODE 与 FOR UPDATE 两者应用场景区别是?前者用于在当前事务处理过程中(比如余额校验)阻止别的事务修改数据(存取余额)这种场景。后者用于当前事务本身需要修改数据。

写不干扰,体现在当事务里执行插入/更新/删除等操作时,会对匹配的行加上 行级排他锁(X 锁),这个锁会 一直持有到事务提交或回滚,不会提前释放。(跟隔离级别无关,任意隔离级别的写操作都会加 X 锁)

注意隔离性与隔离级别是两个不同的概念。对于复杂事务,需要对当前需要处理的数据主动使用 S 锁、X 锁 或 MVCC 等机制,而不是依赖默认的隔离级别处理。

隔离级别

SQL 标准定义的 4 个隔离级别:

隔离级别 能避免的问题 可能出现的问题 特点
READ UNCOMMITTED 无 脏读、不可重复读、幻读 几乎不用
READ COMMITTED 避免脏读 不可重复读、幻读 Oracle 默认
REPEATABLE READ (MySQL 默认 InnoDB) 避免脏读、不可重复读 幻读(InnoDB 里用 next-key lock 也避免了) MySQL 默认
SERIALIZABLE 避免所有问题 事务完全串行,性能最差 很少用

隔离级别解决的问题是读不一致,比如:

  • 脏读 (Dirty Read):读到了别人未提交的数据。
  • 不可重复读 (Non-repeatable Read):同一个事务两次查询同一行,结果不同。
  • 幻读 (Phantom Read):同一个事务两次查询满足条件的行数不一样(新增/删除了行)。

不同隔离级别的适用场景:

  • 金融、电商支付场景 → 更注重一致性 → REPEATABLE READ 或 SERIALIZABLE。
  • 报表、日志分析 → 更注重性能、允许读到最新已提交数据 → READ COMMITTED。

Spring中的事务

Spring中四种基本传播行为

REQUIRED 有则同生共死(同一个事务),无则自立门户(默认传播行为)

REQUIRES_NEW 自求多福(将之前的事务挂起,自己新创建一个事务)

NESTED 父死儿必死,儿死父不死(寄生关系、舔狗)

SUPPORTS 有事务就加进去,没有则不管(懒狗)

Spring中什么异常会导致事务回滚?

Spring默认针对抛出了未检查unchecked异常(继承自 RuntimeException 的异常)或者 Error才回滚事务;其他异常不会触发回滚事务。如果在事务中抛出其他类型的异常,但却期望 Spring 能够回滚事务,就需要指定 rollbackFor属性。

posted on 2019-12-23 21:56  Lemo_wd  阅读(202)  评论(0)    收藏  举报

导航