数据库事务机制

ACID原则

事务机制遵循ACID原则:

  • Atomicity 原子性:事务是一个原子操作,由一系列操作组成。事务的原子性确保所有操作要么完成,要么完全不起作用(完整性)
  • Consistency 一致性:事务执行前后,系统必须确保它所建模的业务处于一致的状态。例如转账,无论事务是否成功,转账者和收款人的总额应该不变。
  • Isolation 隔离性:并发操作相同的数据时,各事务之间相互独立。(但难免会存在冲突
  • Durability 持久性:一旦事务完成,它对数据的改变是持久的,即使数据库发生故障也不影响持久性。

只有保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障(A、I、D是手段,C是目的)


隔离级别

为了解决并发处理相同数据时,事务之间存在冲突的问题,事务有一套隔离机制,设置了隔离级别

  1. READ_UNCOMMITTED 读未提交

    其他事务会读取当前事务尚未提交的更改(暂时缓存的内容)

  2. READ_COMMITTED 读已提交

    其他事务会读取当前事务已经提交的数据(直接读取数据库中已发生更改的内容)

  3. REPEATABLE_READ 可重复读

    其他事务会读取当前事务已经提交的数据,并且其他事务执行过程中不允许再进行数据修改

  4. ISOLATION_SERIALIZABLE 串行化

    完全服从ACID原则,一个事务必须等待其他事务结束之后才能开始执行,效率很低。


READ_UNCOMMITTED 读未提交

image-20240728165009318

各个事务共享一个缓存区域,其他事务会读取当前事务尚未提交的更改(暂时缓存的内容),这样的更改是可以被回滚的。如图事务A读取的数据就是一个毫无意义的脏数据。这种现象之为脏读


READ_COMMITTED 读已提交

image-20240728165158206

读已提交避免了脏读的问题,但是如果当前事务在其他事务2次读取相同数据之间,修改并提交了数据,会导致两次读取结果不一致。这种现象称为不可重复读


READ_REPEATABLE 可重复读 (默认)

image-20240728172233184

可重复读是MySQL的InnoDB存储引擎的默认隔离级别。它规定在其他事务执行时,当前事务不允许修改数据

这样可以有效避免不可重复读的问题,但是仍然不安全。仅仅是禁止了事务执行过程中的UPDATE操作,没有禁止INSERT操作。这样在同一个事务中,第一次和第二次查询同一个范围的数据,如果有其他事务插入了新的数据,就会导致返回的结果不一致。这种现象称为幻读


ISOLATION_SERIALIZABLE 串行化

一个事务必须等待其他事务结束之后才能开始执行,效率很低。