MySQL中的事务及其实现原理

什么是事务

事务是一组操作的集合,它将一系列操作统一发送到数据库进行执行,一旦在这组操作执行的过程中出现错误,则会发生回退操作,数据库状态返回事务执行之前。换句话说,这组操作要么全部成功,要么全部失败。

事务的特性

原子性,一致性,持久性底层依靠两个日志来完成。隔离性依靠锁和MVCC(多版本并发控制)来实现

事务原理

接下来我们分别了解四种特性以及它们的实现原理。

持久性

持久性的实现是依靠 redo log 来实现的。

redo log分为两部分,一部分是redo log buffer(重做日志缓冲) 放在内存中,另一部分是redo log file(重做日志文件)。前者在内存中,后者在磁盘中。

结构

1. 在事务执行过程中,所有对数据的修改会先记录到内存中的redo log buffer中。

2. 当事务提交时,会将redo log buffer中的日志刷新到磁盘上的redo log文件中。

3. 同时,会将数据页的修改从内存刷新到磁盘上。

4. 数据页的修改从内存刷新到磁盘上时如果发生了系统崩溃,在系统恢复时,会从磁盘上的redo log文件重播日志,重新执行事务中的修改操作,来恢复数据。

持久化就是保证修改的数据最后一定能够保存在磁盘。

原子性

原子性是依靠 undo log 实现的 。

undo log也叫做回滚日志文件,它记录了修改前的信息。但是它是一个逻辑日志,每执行一条语句,它里面都会记录一条与其相反的语句。

例如,当我们执行insert 操作后,它内部就会记录一条对应的delete操作。

因此当发生回滚的时候,就可以从里面读取到相应的内容,是数据库回到事务提交之前的状态。

隔离性

隔离性的实现依靠MVCC 和锁来实现

mysql的隔离级别分为四种:

假设A,B两个事务先后开启

1. 脏读:事务B读取了事务A还未提交的修改。如果A回滚,B读到的是脏数据。

2. 不可重复读:事务B多次读取同一数据,事务A在两次读取之间修改了数据,导致B读取到不同结果。

3. 幻读:事务B读取了事务A提交的插入或删除数据操作导致的记录集变化。

读未提交

会出现脏读,不可重复读,幻读

读已提交

会出现不可重复读,幻读

可重复读(默认)

会出现幻读

串行化

事务B只能等事务A提交完后才能访问数据库

MVCC概念

当前读

1. 当前读指的是事务总是读取最新提交的数据,而不使用启动时的旧快照。

2. 当前读会看到其他事务已提交的最新修改,可能会导致不可重复读和幻读现象。

3. 当前读不会看到未提交的数据,可以避免脏读。

5. 在读已提交隔离级别下,默认使用当前读。

6. 当前读可以反映数据库的最新状态,但隔离级别较低。

7. 和快照读不同,当前读不会维护多个版本,节省存储空间。

快照读

1. 当事务启动时,会获取一个数据库的快照,这个快照会保存到事务的开始时间点的数据库版本。

2. 事务中的每次读取都只会从这个快照版本中读取,而不会看到其他并发事务的修改

3. 该快照直到事务全部完成后才会被丢弃,所以同一个事务会看到一致的数据视图

4. 快照读可以避免脏读、不可重复读,但可能会出现幻读。

5. 快照读需要维护多个版本的数据,因此会占用更多存储和内存。

6. 在可重复读隔离级别下,默认使用快照读。


undo log 版本链 会在多个事务对同一条数据进行修改时产生,它里面记录了每次修改的版本。

readview

在读已提交的情况下,到底会访问到数据在undo log 中的哪一个版本,看起来有四条规则,其实总结只有一句话:当前事务只会读取到距离它最近的并且已经提交的事务。

在可重复读情况下,会在第一次当前读,生成一个快照,之后一直读取的都是那个快照。

展开阅读全文

页面更新:2024-03-27

标签:事务   持久性   快照   磁盘   原理   内存   版本   操作   数据库   数据   日志

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top