MySQL InnoDB引擎 事务隔离级别

在 MySQL 的 InnoDB 存储引擎中,定义了四种不同的事务隔离级别,这些隔离级别控制着事务之间的可见性和并发操作的行为,每种隔离级别在数据一致性和并发性能之间进行了不同的权衡。

1. 读未提交(Read Uncommitted)

定义:这是最低的隔离级别,一个事务可以读取另一个事务尚未提交的数据变更。也就是说,在这种隔离级别下,事务可以看到其他事务中未提交的修改,存在脏读的风险。

优点:并发性能最高,因为读操作不会被写操作阻塞,读写操作可以最大程度地并发执行。

缺点:会出现脏读、不可重复读和幻读问题。脏读是指一个事务读取到了另一个事务未提交的数据,如果该事务回滚,那么读取到的数据就是无效的。

示例:

复制代码
-- 会话 1
START TRANSACTION;
UPDATE users SET balance = balance - 100 WHERE id = 1;
-- 此时会话 2 可以读取到会话 1 未提交的修改

-- 会话 2
START TRANSACTION;
SELECT balance FROM users WHERE id = 1; -- 可能读到未提交的余额变化

2. 读已提交(Read Committed)

定义:一个事务只能读取另一个事务已经提交的数据变更。这避免了脏读问题,但仍然可能出现不可重复读和幻读问题。

优点:避免了脏读,保证了读取到的数据都是已经提交的有效数据,数据的可靠性有所提高。

缺点:存在不可重复读和幻读问题。不可重复读是指在一个事务内多次读取同一数据时,由于其他事务的修改,导致每次读取的结果不一致。

示例:

复制代码
-- 会话 1
START TRANSACTION;
UPDATE users SET balance = balance - 100 WHERE id = 1;
COMMIT;

-- 会话 2
START TRANSACTION;
SELECT balance FROM users WHERE id = 1; -- 第一次读取
-- 此时会话 1 提交修改
SELECT balance FROM users WHERE id = 1; -- 第二次读取,结果可能不同

3. 可重复读(Repeatable Read)

定义:这是 InnoDB 存储引擎的默认隔离级别。在一个事务内多次读取同一数据时,会保证读取到的结果是一致的,避免了脏读和不可重复读问题,但在某些情况下仍可能出现幻读。InnoDB 通过 MVCC(多版本并发控制)和间隙锁来实现该隔离级别。

优点:提供了较高的数据一致性,适合大多数业务场景。在同一个事务中,多次读取相同的数据会得到相同的结果,保证了数据的稳定性。

缺点:虽然通过 MVCC 避免了大部分幻读,但在某些复杂的查询场景下仍可能出现幻读问题。幻读是指在一个事务内,当执行范围查询时,由于其他事务插入了符合查询条件的新数据,导致多次查询的结果集不一致。

示例:

复制代码
-- 会话 1
START TRANSACTION;
SELECT * FROM users WHERE age > 20; -- 第一次查询
-- 此时会话 2 插入一条 age > 20 的记录并提交
SELECT * FROM users WHERE age > 20; -- 第二次查询,可能会出现新增的记录

4. 串行化(Serializable)

定义:这是最高的隔离级别,事务之间会串行执行,一个事务执行时会锁定所有涉及的数据,其他事务必须等待该事务完成后才能执行。这避免了脏读、不可重复读和幻读问题,提供了最强的数据一致性保证。

优点:提供了最高的数据一致性,完全避免了并发问题,适合对数据一致性要求极高的场景,如金融交易系统。

缺点:并发性能最低,因为事务之间是串行执行的,会导致大量的锁等待,降低了系统的吞吐量。

示例:

复制代码
-- 会话 1
START TRANSACTION;
SELECT * FROM users WHERE id = 1 FOR UPDATE; -- 对查询结果加锁
-- 此时会话 2 对 users 表的相关操作会被阻塞,直到会话 1 提交或回滚

设置事务隔离级别

可以使用以下 SQL 语句来设置事务隔离级别:

复制代码
-- 设置全局隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL [隔离级别名称];
-- 设置当前会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL [隔离级别名称];

其中,[隔离级别名称] 可以是 READ UNCOMMITTEDREAD COMMITTEDREPEATABLE READSERIALIZABLE

相关推荐
Coder码匠40 分钟前
Dockerfile 优化实践:从 400MB 到 80MB
java·spring boot
李慕婉学姐8 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
哈里谢顿8 小时前
记录一次sql优化记录
mysql
数据大魔方8 小时前
【期货量化实战】日内动量策略:顺势而为的短线交易法(Python源码)
开发语言·数据库·python·mysql·算法·github·程序员创富
Chasing Aurora9 小时前
数据库连接+查询优化
数据库·sql·mysql·prompt·约束
奋进的芋圆10 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin10 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model200510 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉10 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国10 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos