当前位置: 首页 > article >正文

【每日八股】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。事务执行期间多次读取到的同一数据前后可能不一致,因为在此期间另一个事务可能修改了这条记录,并提交了记录,导致不可重复读。


http://www.kler.cn/a/559904.html

相关文章:

  • CSS滚动条原理与自定义样式指南,CSS滚动条样式失效,滚动条样式无效,-webkit-scrollbar无效,overflow不显示滚动条
  • 力扣-贪心-55 跳跃游戏
  • DeepSeek行业应用实践报告-智灵动力【112页PPT全】
  • 登录+注册的前后端以及sql
  • 【面试】Redis 常见面试题
  • Qt QTreeWidget 总结
  • 企业金融数字场景平台:架构设计、实践与未来趋势
  • Linux-Ansible模块完结
  • Linux 内核中关于 CPU 编号和拓扑管理
  • at32f103a+rtt+AT组件+esp01s 模块使用
  • 网络练级宝典-> TCP协议
  • 掌握SQLAlchemy:Python数据库集成的艺术
  • 【R语言】读取CSV数据时,显示[1] PK...<0 行> (或0-长度的row.names)
  • 一:将windows上的Python项目部署到Linux上,并使用公网IP访问
  • 【多模态处理篇八】【DeepSeek增强现实:AR导航实时推理优化】
  • 基于STM32的智能电梯安全监测系统
  • Mybatis常用动态 SQL 相关标签
  • 基于图扑 HT 可视化实现智慧地下采矿可视化
  • 如何在Jenkins上查看Junit报告
  • 91.在 Vue 3 中使用 OpenLayers 非 4326、3857 的投影示例