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

滚雪球学MySQL[5.3讲]:数据库隔离级别与一致性详解:从幻读到MVCC

全文目录:

    • 前言
    • 5.3 隔离级别与一致性
      • 1. 四种隔离级别详解
        • 1.1 读未提交(Read Uncommitted)
        • 1.2 读已提交(Read Committed)
        • 1.3 可重复读(Repeatable Read)
        • 1.4 串行化(Serializable)
      • 2. 幻读、脏读与不可重复读
        • 幻读
        • 脏读
        • 不可重复读
      • 3. MVCC(多版本并发控制)
    • 小结
    • 下期预告:6.1 备份策略

前言

在上一期内容中,我们深入探讨了并发事务的处理,了解了数据库系统在处理多个事务同时进行时所采取的策略,并探讨了事务的四大特性(ACID)。事务的处理是保障数据完整性与系统稳定性的关键,但是事务并发时可能引发一系列问题,如脏读、幻读、不可重复读等。本期,我们将继续沿着并发事务的主题,聚焦在数据库中的隔离级别与一致性上。

本期将系统地介绍数据库中的四种隔离级别,并深入探讨它们对数据一致性的影响,详细解释如幻读、脏读与不可重复读等现象。同时,我们也会介绍数据库中常见的多版本并发控制(MVCC)机制,它如何通过多个数据版本来解决并发事务中数据一致性的问题。

最后,我们将为下期内容备份策略做一个简单的预告,进一步延伸到数据保护与恢复策略的领域。

5.3 隔离级别与一致性

数据库的隔离级别是事务并发处理时的重要机制,它决定了多个事务之间的相互影响程度。数据库系统通过设置不同的隔离级别,来控制并发事务读写操作间的干扰,确保数据的一致性和完整性。

1. 四种隔离级别详解

SQL标准定义了四种事务的隔离级别,从低到高依次为:

  • 读未提交(Read Uncommitted)
  • 读已提交(Read Committed)
  • 可重复读(Repeatable Read)
  • 串行化(Serializable)

每种隔离级别的限制程度不同,影响着数据库并发性能和一致性之间的权衡。下面我们将逐一介绍这些隔离级别的特点。

1.1 读未提交(Read Uncommitted)

读未提交是隔离级别中最低的一个。在这种级别下,一个事务可以读取到其他事务尚未提交的修改,这意味着事务之间没有任何隔离。这种隔离级别可能会引发严重的并发问题,如脏读

脏读(Dirty Read)指的是一个事务读取到了另一个事务尚未提交的数据,如果该事务最终回滚,那么读取到的数据实际上是无效的。

案例演示:
事务A修改了某员工的工资为10000元,但事务A尚未提交。此时,事务B可以读取到该工资为10000元的数据,即使事务A随后回滚,事务B读到的依然是脏数据。

-- 事务A
UPDATE employees SET salary = 10000 WHERE id = 1;
-- 事务B在事务A未提交前读取
SELECT salary FROM employees WHERE id = 1;  -- 返回10000元

读未提交隔离级别不常用,因为它可能导致数据不一致性。

1.2 读已提交(Read Committed)

读已提交是很多数据库系统(如Oracle、SQL Server)的默认隔离级别。它确保一个事务只能读取到其他事务已经提交的数据,避免了脏读的发生。然而,在该隔离级别下,事务可能会出现不可重复读的问题。

不可重复读(Non-repeatable Read)指的是在同一个事务中,执行相同的查询却得到不同的结果,因为其他事务可能在两次查询之间修改了数据。

案例演示:
事务A先读取某员工的工资,事务B在事务A的查询后修改了该员工的工资,事务A再次查询时读到了不同的工资数据:

-- 事务A第一次读取
SELECT salary FROM employees WHERE id = 1;  -- 返回5000元
-- 事务B修改工资并提交
UPDATE employees SET salary = 10000 WHERE id = 1;
-- 事务A第二次读取
SELECT salary FROM employees WHERE id = 1;  -- 返回10000元

虽然读已提交避免了脏读,但并未解决不可重复读的问题。

1.3 可重复读(Repeatable Read)

可重复读隔离级别可以确保在同一事务中,所有的读取操作都会返回一致的数据,即事务不会看到其他事务的修改。它解决了不可重复读的问题。然而,这种隔离级别依然存在幻读的问题。

幻读(Phantom Read)指的是在同一个事务中,某次查询返回的行数与后续的相同查询返回的行数不同,因为另一个事务插入了新数据。

案例演示:
事务A查询工资大于5000元的员工数,事务B插入了一名符合条件的新员工,事务A再次查询时返回了不同的结果:

-- 事务A第一次查询
SELECT COUNT(*) FROM employees WHERE salary > 5000;  -- 返回5
-- 事务B插入一条新记录并提交
INSERT INTO employees (id, name, salary) VALUES (6, 'Bob', 6000);
-- 事务A第二次查询
SELECT COUNT(*) FROM employees WHERE salary > 5000;  -- 返回6

可重复读在MySQL等数据库中是默认隔离级别,它能保证事务中的读取数据一致性,但无法避免幻读。

1.4 串行化(Serializable)

串行化是最高的隔离级别,确保事务之间完全隔离,相当于事务按顺序一个接一个执行。这种级别可以避免所有并发问题,如脏读、不可重复读和幻读,但也会显著降低数据库的并发性能。

案例演示:
在串行化隔离级别下,事务A和事务B不能同时执行,如果事务A正在读取或修改数据,事务B必须等待事务A提交后才能开始执行。

-- 事务A执行
SELECT COUNT(*) FROM employees WHERE salary > 5000;
-- 事务B必须等待事务A提交后才能开始

串行化提供了最强的数据一致性保证,但代价是性能上的巨大开销。

2. 幻读、脏读与不可重复读

为了更好地理解事务隔离级别对数据库一致性的影响,下面我们深入分析三种并发读写问题。

幻读

幻读是指在同一个事务中,两次相同的查询操作返回了不同的结果,因为在这两次查询之间,其他事务插入了新数据。幻读会导致查询结果的行数发生变化,而不仅仅是某些行的具体数据被修改。

脏读

脏读发生在一个事务读取了另一个未提交事务的数据。如果该未提交事务最终回滚,那么该读取的数据就变成了无效的,这就是“脏”的来源。

不可重复读

不可重复读意味着在同一事务中,两次读取同一行的数据结果不同。一般是由于另一个事务修改了该行数据并提交,导致前后读取结果不一致。

3. MVCC(多版本并发控制)

为了解决并发读写问题,很多数据库(如MySQL的InnoDB存储引擎)使用了MVCC(多版本并发控制)。MVCC允许数据库同时支持多个事务读取同一数据行的不同版本,避免了锁竞争问题,提升了系统并发性能。

MVCC通过为每一行数据创建多个版本来处理并发事务。每个事务在读取数据时,会根据事务的开始时间看到一个数据的历史版本,而不是最新的值,这就避免了不可重复读和幻读的问题。

案例演示:
在MVCC机制下,事务A读取了一个员工的工资,在事务A期间,事务B修改了该员工的工资并提交。然而,事务A读取的仍然是事务开始时的数据版本,而不会受到事务B修改的影响。

-- 事务A开始时读取工资
SELECT salary FROM employees WHERE id = 1;  -- 返回5000元
-- 事务B修改工资并提交
UPDATE employees SET salary = 10000 WHERE id = 1;
-- 事务A再次读取工资,仍返回5000元
SELECT salary FROM employees WHERE id = 1;  -- 返回5000元

通过MVCC,事务A读取到的是事务开始时的历史版本,而不受事务B提交数据的影响,这就避免了不可重复读和幻读的问题。

小结

本期我们深入探讨了数据库中的隔离级别与一致性,详细介绍了SQL标准定义的四种隔离级别及其应用场景,分析了幻读、脏读和不可重复读等常见问题,并介绍了多版本并发控制(MVCC)这一重要机制。理解隔离级别与一致性的概念是优化数据库性能和保证数据一致性的关键。

下期预告:6.1 备份策略

数据安全是数据库管理中的核心要素之一,尤其是在处理大规模数据的系统中,意外的系统故障、硬件损坏或数据操作错误可能导致数据丢失甚至影响业务连续性。因此,制定并实施有效的备份策略,确保数据可以在任何情况下得到恢复,是数据库管理员必须掌握的技能。下期我们将详细探讨不同的备份策略,包括全量备份、增量备份与差异备份的使用场景,如何平衡备份效率与恢复时间,以及如何利用现代工具进行数据库自动化备份,敬请期待!


http://www.kler.cn/news/331683.html

相关文章:

  • 数据结构(二叉树)
  • 基于SpringBoot+Vue的汽车保险理赔系统
  • WDG看门狗在stm32中的应用
  • 在 VSCode IDE 中,使用 ESP32-S3 的 USB 接口进行调试
  • ElasticSearch备考 -- 异步检索
  • Node.js env 环境变量多种配置方式
  • 软件测试学习笔记丨Pytest 学习指南
  • unity 默认渲染管线材质球的材质通道,材质球的材质通道
  • 学习docker第二弹------基本命令[帮助启动类命令、镜像命令、容器命令]
  • [深度学习][python]yolov11+deepsort+pyqt5实现目标追踪
  • 28 Vue3之搭建公司级项目规范
  • Nginx编译所需基本库pcre、zlib、openssl
  • [uni-app]小兔鲜-06地址+sku+购物车
  • Ruby 数组(Array)
  • 【Docker从入门到进阶】04.高效实践
  • 基于CNN+Transformer混合模型实现交通流量时序预测(PyTorch版)
  • JSON 全知全解:深入探索 JSON 的奥秘
  • 太原网站制作打造企业网站的关键要素
  • 中级软件设计师:一文搞懂下午第一题——数据流图技术
  • 2、项目配置设计(上)