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

相关推荐
lkbhua莱克瓦241 天前
Java练习-正则表达式 1
java·笔记·正则表达式·github
yue0081 天前
C#类继承
java·开发语言·c#
凯芸呢1 天前
Java中的数组(续)
java·开发语言·数据结构·算法·青少年编程·排序算法·idea
竹竹零1 天前
JacksonUtil--序列化与反序列化
java·开发语言·windows
钱多多_qdd1 天前
基础篇:IoC(三):Bean实例化策略InstantiationStrategy
java·spring
float_com1 天前
【java基础语法】---- 综合训练
java
Dyan_csdn1 天前
springboot系统设计选题3
java·spring boot·后端
sheji34161 天前
【开题答辩全过程】以 基于Java的旅游网站的设计与开发为例,包含答辩的问题和答案
java·开发语言·旅游
ABdolphin1 天前
Spring-cloud 主键Eureka
java·云原生·eureka
Aesopcmc1 天前
Maven打包时指定输出路径、以时间戳命名包名和路径名,结合IDEA以指令脚本方式动态配置输出目录
java·自动化·maven·intellij-idea