编辑
2024-01-14
编程
00

目录

1.1 ACID
1.2 隔离性
1.2.1 隔离级别
1.2.2 MVCC
1.3 并发问题

1.1 ACID

我们聊到事务,通常会说到 ACID,指原子性(Atomicity),,一致性(Consistency),隔离性(Isolation),持久性(Durability)。ACID是事务的特性,也是事务本质的最重要体现。

  • 原子性:all-or-nothing

我们经常会在多线程中看到原子性这个词,它是指具有原子性的一批指令,能被CPU一次性执行完。

ACID的原子性,也类似。指一次事务请求中的所有语句,要么都成功,要么都不处理。也就是整体提交,或整体回退。

  • 一致性:状态一致

与分布式理论CAP中的一致性不一样,这里的一致性不是说数据一致,而是指规则一致。也就是在用户设置得规则(约束)下,所有语句执行前后数据的状态必须保存一致(都符合规则)。

例如:我们规定字段不能为空,那么不管是insert, update前后,这个字段都不能存在为空的数据。

  • 隔离性

事务之间(按照设置得隔离级别)相互隔离,互不影响。这个在下文会重点讨论

  • 持久性

持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

1.2 隔离性

ACID 对于一个数据库很重要,作为一个开发,我们往往最需要关注的是隔离性

1.2.1 隔离级别

事务的隔离级别分为四个:

  • 读未提交(read uncommitted)

一个事务的修改,即使没有提交,也能被别的事务所看见。

  • 读提交(read committed)

一个事务开始时,只能看见已经提交的事务所做的修改。

  • 可重复读(repeatable read)

同一个事务,在事务期间,看到的数据都是一样的,不会被别的事务所改变。这是 mysql 默认的隔离级别。

  • 串行化(serializable )

强制事务串行执行,简单说就是对同一行记录,读加读锁,写加写锁,读写出现锁冲突,排队等待锁释放。 这种模式下,事务的锁竞争变得平方,容易出现超时,很少会使用这种模式。

隔离级别示例图如下:

隔离级别.jpg

隔离级别search1search2
读未提交age = 5age = 5
读提交age = 10age = 5
可重复读age = 10age = 10

而串行化在事务B开启事务时会开启失败,等待事务A commit 后,开始执行。

1.2.2 MVCC

全称:muti-version concurrency control, 即多版本并发控制。

这是 mysql 在 读提交、可重复读 隔离级别下,为了保证读写的并发性而设计的方案。

MVCC 的工作原理基于三个概念,分别是:行的隐藏列undo log 版本链read view

  • 行的隐藏列

每一行数据都有两列隐藏数据: trx_id, roll_pointer

trx_id 表示当前这行数据的最新事务id,只要任意一个事务对数据进行修改,该事务的id就会被记录到该字段

roll_pointer 保存上一个版本数据的指针

  • undo log 版本链

Undo Log是MySQL的三大日志之一, 当我们对记录做了变更炒作时,就会产生一条 undo 记录,用以在发生异常或手动回滚事务时,回滚到历史版本数据。

如下: undo_log.png

  • Read View

Read View 中存放着一个列表,每一个事务都会创建一条记录,字段如下

creator_trx_idm_idsmin_trx_idmax_trx_id
当前事务id所有活跃的事务id(未提交)m_ids中最小的事务id分配给下一个事务的id

这个视图决定了事务的可见性

事务在查询时会建立一条记录,查询数据的流程如下:

查询流程.png

在可重复读隔离级别下,如果事务只是进行查询操作,那么就**「只会在第一次查询的时候生成 ReadView 快照,这一点和读提交隔离级别是最大的区别」**。

1.3 并发问题

  • read uncommitted - Dirty Read

读未提交 - 脏读

读未提交隔离级别的定义是,「一个事务的修改,即使没有提交,也能被别的事务所看见。」

  1. 在事务A执行过程中,事务A对数据资源进行了修改,事务B读取了事务A修改后的数据
  2. 由于某些原因,事务A并没有完成提交,发生了 Roll Back,则事务B读取的数据就是脏数据。

这种现象就是 脏读, 隔离级别修改为 read committed ,可以解决脏读问题

  • read committed - Nonrepeatable Read

读提交 - 不可重复读

对于读提交的隔离级别来讲,在 MVCC 中,生成 Read View 的时机是,每一次查询的时候,这就会有一个现象,当前事务在进行的过程中,每次查询生成的 Read View 都有可能不同,所以同一条数据读取到的数据可能不同,这种现象就是不可重复读

隔离级别修改为 repeatable read,可以解决该问题

  • repeatable read - Phantom Read

可重复读 - 幻读

在可重复读的隔离级别下,我们第一次发生查询时就生成了 Read View ,后续不再生成,这是其他事务区插入一条数据(比如:id=10),然后提交结束,这时我们海狮看不到 id = 10 的记录,这种情况下,我们也去插入一条 id = 10 的数据,就会出现逐渐冲突。这种情况就是幻读。

本文作者:Yui_HTT

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!