【每日八股】MySQL篇(二):事务

MySQL 之事务的四大特性(ACID)?

  • 原子性(Atomicity):一个事务被视为一个不可分割的最小工作单元,整个事务中的操作要么全部成功,要么全部失败回滚,对于一个事务而言,不可能只执行其中一部分操作,这就是事务的原子性。
  • 一致性(Consistency):数据库总是从一个一致性的状态转移到另一个一致性的状态;
  • 隔离性(Isolation):一个事务所做的修改在最终提交前,其它事务是不可见的;
  • 持久性(Durability):一旦事务提交,那么其所做的修改就会永远保存在数据库当中。此时即使系统崩溃,修改的数据也不会丢失。

概括:MySQL 事务的四大特性分别是原子性、一致性、隔离性和持久性。

并发事务会出现什么问题?

  • 脏读:指的是读取到了其他事务未提交的数据。未提交意味着某条事务的执行可能失败,造成回滚,也就是读取到的数据可能未在数据库当中,也就是读取到了不存在的数据。读取到不一定存在的数据就是脏读。
  • 不可重复读:不可重复读指的是在同一个事务内,不同时间读取到的数据可能是不一样的,这个现象产生的原因是读取的数据被其它事务修改并提交了。不可重复读常出现在更新操作中。【可重复读:指的是在同一个事务内,最开始读取到的数据和事务结束前任意时刻读取到的数据是一致的】
  • 幻读:在一个事务中,两次相同的查询返回了不同的结果,尽管两次查询之间没有修改或删除现有的数据,但可能有新的插入。

MySQL 的事务隔离级别

  • 读未提交(Read Uncommitted):指一个事务还未提交时,它所做的变更就可以被其它事务看到。(隔离级别最低,可能导致脏读、幻读和不可重复读)
  • 读已提交(Read Committed):指一个事务提交之后,它所做的变更才能被其它事务看到。(避免了脏读,但可能出现不可重复读和幻读)
  • 可重复读(Repeatable Read):确保在同一事务中每次读取到的同一数据的结果都是一致的。(MySQL 的默认隔离级别,避免了脏读和不可重复读,但在某些情况下会出现幻读)
  • 串行化(Serializable):会对记录加上读写锁,在多个事务对某条记录进行操作时,如果发生了读写冲突,那么后访问的事务必须等待前一个事务执行完成才能执行。(最高的隔离级别,不会发生脏读、幻读以及不可重复读,但是性能开销也是最大的)

在不同事务隔离级别下会发生什么现象?

  • 读未提交:脏读、幻读、不可重复读;
  • 读已提交:幻读、不可重复读;
  • 可重复读:幻读;
  • 串行化:无;

解决脏读现象:将隔离级别升级到"读已提交";

解决不可重复读现象:将隔离级别升级到"可重复读";

解决幻读:不建议将隔离急别升级到串行化,因为这样会导致在并发事务时性能很差。

MVCC 实现原理?

MVCC(Multi-Version Concurrency Control,版本控制)是一种用于数据库管理系统中的并发控制方法,允许多个事务同时访问数据库而不阻塞MVCC 通过维护数据的多个版本来实现高并发和一致性

MVCC 的实现原理

一. 版本链:

  • 每条记录都有一个版本链 ,每个版本包含数据内容和创建该版本的事务的ID(trx_id);
  • 事务更新时,会创建一个新版本并添加到版本链中,旧版本保留

二. Read View:

  • 事务在执行时会生成一个 Read View用于确定哪些版本对当前事务可见
  • Read View 包含当前活跃事务 ID 列表、最小事务 ID (up_limit_id)和下一个事务 ID(low_limit_id);

三. 可见性判断:

  • 事务读取数据 时,根据 Read View 判断版本链中哪个版本可见;
  • 如果版本的事务 ID 小于 up_limit_id 且不在活跃事务列表中,则该版本可见;
  • 如果版本的事务 ID 等于当前事务ID,则该版本可见;
  • 如果版本的事务 ID 大于等于 low_limit_id,则该版本不可见;

四. 事务提交与回滚:

  • 事务提交时,其修改的版本对其他事务可见;
  • 事务回滚时,其修改的版本被标记为无效;

MVCC 的优点

  • 高并发:读操作不会阻塞写操作,写操作也不会阻塞读操作;
  • 一致性:事务读取的数据是一致的,不受其他事务影响;

MVCC 的缺点

  • 存储开销:需要维护多个版本,增加存储空间;
  • 清理机制:需要定期清理旧版本,防止存储膨胀;

幻读是如何解决的?

  • 快照读(普通 select 语句):通过 MVCC 方式解决幻读,在可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其它事务插入了一条数据,也是查询不出这条数据的。
  • 当前读(select ... for update 语句):通过 next-key lock(记录锁 + 间隙锁)方式解决了幻读。

注意,MySQL 可重复读隔离级别没有解决幻读,而是尽可能地避免了幻读现象的发生。

读提交(Read Committed)怎么实现?

读提交隔离级别是在每一次读取数据时,都会生成一个新的 Read View。事务执行期间多次读取到的同一数据前后可能不一致,因为在此期间另一个事务可能修改了这条记录,并提交了记录,导致不可重复读。

相关推荐
李少兄2 分钟前
MySQL中的UNION操作符
android·数据库·mysql
在成都搬砖的鸭鸭5 分钟前
【MySQL】表连接原理
android·mysql
Henry_Wu00128 分钟前
ubuntu20.04 突破文件数限制
服务器·网络·数据库
局外人_Jia1 小时前
【C# 变量字符串还原转义字符】
linux·数据库·windows·正则表达式·c#·字符串·indexof
Gauss松鼠会1 小时前
GaussDB 闪回恢复技术详解与应用实践
数据库·sql·哈希算法·database·gaussdb
leegong231111 小时前
什么是 OCP 数据库专家
数据库·oracle
CatalyzeSec2 小时前
Deepseek-ClickHouse数据库的安全策略
数据库·clickhouse·web安全·网络安全
三天不学习2 小时前
MongoDB面试宝典【刷题系列】
数据库·mongodb·面试
和道一文字yyds3 小时前
MySQL 中的事务隔离级别有哪些?MySQL 默认的事务隔离级别是什么?为什么选择这个级别?数据库的脏读、不可重复读和幻读分别是什么?
数据库·mysql
小王努力学编程3 小时前
【MySQL篇】MySQL操作库
数据库·mysql