有时博客内容会有变动,首发博客是最新的,其他博客地址可能未同步,请认准
https://blog.zysicyj.top
在MySQL中,事务隔离级别(Transaction Isolation Levels)决定了一个事务在并发访问数据库时的行为,以及一个事务中的操作是否会被其他事务看到。MySQL支持的事务隔离级别有四种,每种隔离级别都提供了不同程度的数据一致性和并发性能权衡。下面是详细的介绍:
1. 读未提交(Read Uncommitted)
特点: - 最低的隔离级别。 - 事务中的修改,即使没有提交,对其他事务也是可见的。 - 可能导致“脏读”(Dirty Read):一个事务能够读取到另一个未提交事务修改的数据。
适用场景: - 对数据一致性要求最低,但需要最高并发性能的场景。
设置方法:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
2. 读已提交(Read Committed)
特点: - 事务只能读取已经提交的数据。 - 解决了脏读问题,但可能会导致“不可重复读”(Non-Repeatable Read):同一事务中的相同查询在不同时间读取到的数据可能不同,因为其他事务可能在中间提交了修改。
适用场景: - 大多数读操作比写操作频繁的OLTP(在线事务处理)系统。
设置方法:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
3. 可重复读(Repeatable Read)
特点: - MySQL默认的隔离级别。 - 事务开始后,看到的数据是一致的,除非事务自己修改了数据。 - 解决了不可重复读问题,但可能会导致“幻读”(Phantom Read):一个事务在读取某个范围内的行时,另一个事务在该范围内插入了新行,前一个事务再读取时会看到“幻影”行。
适用场景: - 大多数常见的事务处理需求,能够平衡数据一致性和并发性能。
设置方法:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
4. 序列化(Serializable)
特点: - 最高的隔离级别。 - 强制事务按顺序执行,完全避免了脏读、不可重复读和幻读问题。 - 可能导致大量锁争用,影响并发性能。
适用场景: - 对数据一致性要求极高且并发度较低的场景。
设置方法:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
不同隔离级别下的问题示例
1. 脏读(Dirty Read)
在读未提交隔离级别下,事务可以读取未提交的数据,可能导致读取到临时状态的数据。
-- Session 1
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- Session 2
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;
SELECT balance FROM accounts WHERE id = 1;
-- 可以读取到未提交的负值
2. 不可重复读(Non-Repeatable Read)
在读已提交隔离级别下,事务中的两次相同查询可能返回不同的结果。
-- Session 1
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
SELECT balance FROM accounts WHERE id = 1;
-- Session 2
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;
-- Session 1
SELECT balance FROM accounts WHERE id = 1;
-- 可能返回不同的结果
3. 幻读(Phantom Read)
在可重复读隔离级别下,事务在读取某个范围内的数据时,另一事务插入了新数据。
-- Session 1
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT * FROM accounts WHERE balance > 1000;
-- Session 2
START TRANSACTION;
INSERT INTO accounts (id, balance) VALUES (3, 1500);
COMMIT;
-- Session 1
SELECT * FROM accounts WHERE balance > 1000;
-- 可能返回多出的记录
查看和设置当前事务隔离级别
查看当前隔离级别:
SELECT @@transaction_isolation;
设置当前隔离级别:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
总结
选择合适的隔离级别需要在数据一致性和并发性能之间进行权衡。一般情况下,MySQL默认的可重复读(Repeatable Read)能够满足大多数应用场景的需求,但在特定情况下,可以根据业务需求调整为其他隔离级别。


