基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

MySQL数据库的事务隔离级别

知识点图片

讲解MySQL四种事务隔离级别,分析其如何解决脏读、不可重复读、幻读等并发问题,并提供MySQL中的查看与设置方法。

我们来详细讲解一下 MySQL 数据库的事务隔离级别。这是一个非常核心且重要的概念,直接关系到数据库的并发性能和数据一致性。

什么是事务和隔离性?

首先,我们简单回顾一下事务(Transaction)的四大特性(ACID):

  1. 原子性 (Atomicity): 事务是一个不可分割的工作单元,事务中的操作要么都发生,要么都不发生。
  2. 一致性 (Consistency): 事务必须使数据库从一个一致性状态变换到另一个一致性状态。
  3. 隔离性 (Isolation): 多个并发事务之间是相互隔离的,一个事务的执行不应被其他事务干扰。
  4. 持久性 (Durability): 一个事务一旦被提交,它对数据库中数据的改变就是永久性的。

我们今天要讨论的事务隔离级别,就是为了定义隔离性 (Isolation) 的程度。因为完全的隔离(即让所有事务串行执行)会极大地降低数据库的并发性能。因此,SQL 标准定义了四种不同的隔离级别,允许开发者在数据一致性并发性能之间做出权衡。

并发事务可能带来的问题

在讨论隔离级别之前,我们必须先了解,如果隔离性不足,多个事务并发执行时可能会遇到哪些问题:

  1. 脏读 (Dirty Read):

    • 定义: 一个事务读取到了另一个事务尚未提交的数据。如果那个事务最终回滚(Rollback),那么第一个事务读取到的就是无效的“脏”数据。
    • 例子: 事务A修改了某行数据但未提交,事务B读取了这行被修改的数据。之后事务A回滚,那么事务B读取到的数据就是不存在的。
  2. 不可重复读 (Non-repeatable Read):

    • 定义: 在同一个事务内,多次读取同一行数据,得到的结果却不一样。这是因为在两次读取之间,有另一个事务修改了这行数据并提交了。
    • 重点: 关注的是同一行数据修改(UPDATE)或删除(DELETE)
    • 例子: 事务A读取某商品价格为100元。此时事务B将该商品价格修改为120元并提交。事务A再次读取该商品价格时,发现变成了120元。
  3. 幻读 (Phantom Read):

    • 定义: 在同一个事务内,多次执行同一个范围查询,返回的结果集行数不同。这是因为在两次查询之间,有另一个事务插入(INSERT)或删除(DELETE)了符合该查询条件的数据并提交了。
    • 重点: 关注的是一个范围内数据的增加或减少。它和不可重复读的区别在于,幻读是行数变了,像出现了“幻影”一样。
    • 例子: 事务A查询所有年龄大于20岁的员工,得到10条记录。此时事务B插入一个年龄为25岁的新员工并提交。事务A再次执行相同的查询,发现得到了11条记录。

四种事务隔离级别

SQL 标准定义了以下四种隔离级别,从低到高,隔离性越来越强,但并发性能通常也越来越差。


1. 读未提交 (Read Uncommitted)

  • 隔离程度: 最低级别。一个事务可以看到其他事务未提交的修改。
  • 解决的问题: 无。
  • 可能出现的问题: 脏读、不可重复读、幻读。
  • 应用场景: 性能要求极高,但对数据一致性要求很低的场景。实际应用中非常罕见。

2. 读已提交 (Read Committed)

  • 隔离程度: 一个事务只能读取到其他事务已经提交的数据。这是大多数主流数据库(如 Oracle, SQL Server)的默认隔离级别。
  • 解决的问题: 避免了脏读
  • 可能出现的问题: 不可重复读、幻读。
  • 工作原理(常见实现): 通过 MVCC (多版本并发控制),每次 SELECT 时都生成一个新的 Read View(读视图),所以能看到其他已提交事务的修改。

3. 可重复读 (Repeatable Read)

  • 隔离程度: 保证在同一个事务中,多次读取同一行数据的结果都是一致的。这是 MySQL InnoDB 存储引擎的默认隔离级别
  • 解决的问题: 避免了脏读不可重复读
  • 可能出现的问题: 标准 SQL 定义下,仍然可能出现幻读
  • 工作原理(InnoDB实现): 通过 MVCC 实现。事务在开始时创建一个 Read View(快照),后续的所有读取操作都基于这个快照,直到事务结束。
  • 特殊之处 (MySQL/InnoDB): MySQL 的 InnoDB 引擎在 REPEATABLE READ 级别下,通过间隙锁 (Gap Lock) 机制,在很大程度上解决了幻读问题。因此,很多人认为 MySQL 的可重复读级别已经杜绝了幻读。

4. 可串行化 (Serializable)

  • 隔离程度: 最高级别。强制事务串行执行,即一个接一个地执行。
  • 解决的问题: 避免了脏读不可重复读幻读
  • 可能出现的问题: 无。
  • 工作原理: 通常通过对读取的每一行数据都加上锁(读写锁),以及范围锁,来阻止其他事务的并发修改。
  • 缺点: 并发性能最差,因为大量的读写操作都会被阻塞,容易导致超时和死锁。

总结表格

隔离级别 脏读 (Dirty Read) 不可重复读 (Non-repeatable Read) 幻读 (Phantom Read)
读未提交 (Read Uncommitted) ❌ (可能发生) ❌ (可能发生) ❌ (可能发生)
读已提交 (Read Committed) ✅ (避免) ❌ (可能发生) ❌ (可能发生)
可重复读 (Repeatable Read) ✅ (避免) ✅ (避免) ⚠️ (标准下可能发生, InnoDB基本避免)
可串行化 (Serializable) ✅ (避免) ✅ (避免) ✅ (避免)

在 MySQL 中如何操作

1. 查看当前隔离级别

可以查看全局(GLOBAL)或当前会话(SESSION)的隔离级别。

sql
-- 查看当前会话隔离级别
SELECT @@transaction_isolation;

-- 查看系统全局隔离级别
SELECT @@global.transaction_isolation;

注意: 在旧版本 MySQL 中,变量名是 tx_isolation,现在推荐使用 transaction_isolation

2. 设置隔离级别

可以为当前会话设置,也可以为之后所有的新连接设置全局级别。

sql
-- 设置当前会话的隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

-- 设置全局隔离级别 (对新建立的连接生效)
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

可用的级别值包括:READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE

如何选择合适的隔离级别?

  • REPEATABLE READ (MySQL 默认): 对于大多数应用来说,MySQL 的默认级别已经足够好。它提供了很高的数据一致性,同时由于 MVCC 的存在,性能也很好。它能防止脏读和不可重复读,并且在 InnoDB 中基本避免了幻读。
  • READ COMMITTED: 如果你的应用不需要“可重复读”的保证(即一个事务内多次读取同一行数据可以不同),并且希望获得更高的并发性(因为它产生的锁范围比可重复读小),那么这个级别是不错的选择。很多互联网公司会将其设置为默认级别。
  • SERIALIZABLE: 只有在对数据一致性要求极高,且能接受性能损失的情况下才使用,例如涉及银行转账、库存扣减等绝对不能出错的场景。
  • READ UNCOMMITTED: 几乎不使用。

希望这个详细的解释能帮助你完全理解 MySQL 的事务隔离级别!

00:00
00:00