MySQL事务原理和MVCC多版本并发控制

admin 2024年10月13日00:56:04评论22 views字数 2838阅读9分27秒阅读模式

1、MySQL事务

事务就是通过一组数据库操作,保证数据的完整性和一致性,即使在多用户并发操作或系统崩溃的情况下,也能确保数据库的可靠性。

事务可以看作是一个不可分割的工作单元,所有的操作要么全部执行成功,要么全部回滚。

1.1、事务的四大特性(ACID)

原子性 (Atomicity):事务中的操作是不可分割的原子单元,事务中的操作要么全部执行,要么全部回滚。

一致性 (Consistency):执行的结果必须使数据从一个一致状态转变到另一个一致状态。无论事务成功与否,数据库的数据完整性约束不会被破坏。

隔离性 (Isolation):多个事务并发执行时,一个事务的操作对其他事务是隔离的。未提交的事务的中间状态对其他事务是不可见的,事务的隔离性可以通过多种隔离级别来控制。

持久性 (Durability):一旦事务提交,其对数据库的更改是永久性的。即使系统崩溃,数据也不会丢失。

1.2、事务的组成
1、Begin: 明确开始一个事务;
2、操作语句: SQL 操作,如 INSERT、UPDATE、DELETE 等;
3、Commit: 提交事务,将事务中的所有操作永久保存到数据库;
4、Rollback: 回滚事务,撤销该事务中所有已执行的操作,恢复到事务开始之前的状态。
1.3、事务的实现机制

Redo Log(重做日志)

InnoDB 存储引擎通过 Redo Log 保证事务的持久性。事务在修改数据时,首先将日志写入到 Redo Log 中,再异步将数据写入到磁盘中。保证事务提交后,数据库即使崩溃,仍然可以通过Redo Log恢复到提交的状态。

Undo Log(回滚日志)

用于保存事务修改前的数据,如果事务失败或者执行了回滚操作,通过 Undo Log 恢复数据到事务执行之前的状态。支持 MVCC(多版本并发控制)机制,允许读操作在并发事务下读取历史版本的数据,避免读取未提交的数据。

锁机制

InnoDB 使用不同类型的锁实现事务的隔离性。

行锁(Record Lock):锁定某一行记录,防止其他事务对该行进行修改。

间隙锁(Gap Lock):锁定索引记录之间的“间隙”,防止其他事务在这个间隙中插入数据。

临键锁(Next-Key Lock):锁定索引记录及其前面的间隙,防止幻读问题。

事务隔离级别

InnoDB引擎中定义了四种隔离级别,级别越高事务隔离性越好,但性能越低,隔离性是由MySQL的各种锁和MVCC机制实现。

隔离级别 定义或作用 可能产生的问题
读未提交 允许读取未提交的数据 脏读、不可重复读、幻读
读已提交 能读取已提交的数据,防止脏读 不可重复读、幻读
可重复读

保证事务内的多次读取结果一致,防止不可重复读。

InnoDB 默认的隔离级别,并通过 Next-Key Lock 防止幻读

幻读
串行化 完全串行化事务的执行,事务之间完全隔,性能最低,隔离级别最高
1.4、并发问题

脏读 (Dirty Read)

脏读是一个事务读取了另一个事务尚未提交的数据,后者可能会回滚,导致前一个事务读取到了无效数据。

不可重复读 (Non-repeatable Read)

不可重复读是因其他事务修改了数据,在同一事务中多次读取同一数据,每次读取的结果可能不同。

幻读 (Phantom Read)

幻读是一个事务读取范围内的数据时,另一个事务插入了新数据,导致前一个事务在读取相同范围时,发现了“幻影”记录。

1.5、大事务的影响

并发情况下,数据库连接池容易被撑爆;锁定太多数据,造成大量的阻塞和锁超时;

执行时间长,容易造成主从延迟;回滚所需的时间比较长;undo log膨胀;容易导致死锁。

1.6、事务优化实践原则

将查询等数据准备操作放到事务外,不同隔离级别影响不一样:读已提交(RC)没影响,可重复读(RR)取到数据可能会不一样;

更新等涉及加锁的操作尽可能放在事务靠后的位置,先insert再update ,因update可能会影响到其他操作,需等待事务提交;

事务中避免一次性处理太多数据,可以拆分成多个事务分次处理,能异步处理的尽量异步处理;

事务中避免远程调用,远程调用要设置超时,防止事务等待时间太久。

2、MVCC多版本并发控制

MVCC,全称Multi-Version Concurrency Control,多版本并发控制。用于在并发环境下实现事务的隔离性和一致性,通过维护数据的多个版本允许并发读写操作,不需要加锁,从而提高数据库的性能和可扩展性。

2.1、MVCC 的基本原理

MVCC 通过保存数据的多个版本(版本快照)实现数据库的并发控制。每当对数据进行更新操作时,数据库不会直接覆盖原有数据,而是为数据创建一个新的版本。通过这种方式,不同的事务可以在不同时间点读取到相应版本的数据,而不需要加锁。

MVCC 的实现依赖于两个核心机制:

(1)快照读:读取数据时,事务会读取数据的一个历史版本(快照),而非直接读取当前最新的版本。

(2)版本链:在对某一行数据进行更新时,数据库不会直接覆盖旧版本,而是创建一个新版本,并将该版本和旧版本通过指针链接起来,形成版本链。

2.2、MVCC 的工作原理

1、Undolog多版本链

MVCC通过为每行数据项维护多个版本实现并发控制,当一个事务对数据进行修改时,它不会直接覆盖现有的数据,而是创建一个新的版本,这些不同数据版本形成了单向版本链。

2、Readview视图组成

readview视图由当前活跃的事务ID数组,和其他3部分组成,分别是最小事务min_ids,最大事务max_id,当前事务creator_trx_id。

3、Readview创建时机

事务开始时,ReadView不会立即创建,而是等到第一次读取数据时。不同隔离级别,创建时机不一样。

读已提交(RC)隔离级别:每次读取数据时都会创建新的 ReadView,保证事务读取到的是其他事务提交的最新数据。

可重复读(RR)隔离级别:  ReadView 只会在事务第一次读取数据时创建,并在整个事务中保持不变,保证事务的快照一致性。

4、可见性规则

当版本的事务ID小于min_ids时,该版本在Read View创建之前已经提交,对当前事务可见

当版本的事务ID大于max_id时,该版本在Read View创建之后生成,对当前事务不可见

当版本的事务ID在min_ids和max_id之间,如果版本的事务ID不在活跃事务列表中,该版本已经提交,对当前事务可见;如果版本的事务ID活跃事务列表中,该版本尚未提交,对当前事务不可见。

如果是当前事务creator_trx_id操作的数据,对当前事务可见

5、快照读与当前读

查询select语句属于快照读;增删改类语句属于当前读,读的是数据库已经提交的数据。

6、数据如何可见

从undolog版本链的头部开始遍历,根据数据版本的事务ID,结合readview以及可见性的规则,可以判断哪些数据版本对当前事务是可见的。

3、我的公众号

敬请关注我的公众号:大象只为你,持续更新技术知识......

原文始发于微信公众号(大象只为你):MySQL事务原理和MVCC多版本并发控制

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月13日00:56:04
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   MySQL事务原理和MVCC多版本并发控制https://cn-sec.com/archives/3259220.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息