深入理解 MySQL 事务的 4 种隔离级别
什么是事务?
事务是指一系列数据库操作作为一个统一的工作单元,要么全部执行,要么全部回滚的过程。事务一般具有四个属性,ACID:
- Atomicity(原子性)
- Consistency(一致性)
- Isolation(隔离性)
- Durability(持久性)
本文重点讲解事务的隔离性。
事务的隔离级别
MySQL 提供了四种事务隔离级别。这些级别在多个客户端并发访问相同数据时会产生不同的影响。以下是四种隔离级别,从低到高排列:
- READ UNCOMMITTED(读未提交)
- READ COMMITTED(读已提交)
- REPEATABLE READ(可重复读)
- SERIALIZABLE(序列化)
接下来,我们会对这四种级别进行详细说明。
READ UNCOMMITTED
READ UNCOMMITTED 是最低的隔离级别。在此级别下,一个事务可以读取另一个未提交事务修改的数据。这种隔离级别很少使用,因为它可能导致脏读(读取未经提交的数据)和更新丢失。
以下是一个示例,演示了读取未提交数据的情况:
-- session1
BEGIN;
UPDATE users SET age = age+1 WHERE name = 'Alice';
-- session2
SELECT age FROM users WHERE name = 'Alice';
-- 返回结果可能是 15,也可能是 16,这取决于 session1 的操作是否提交
READ COMMITTED
READ COMMITTED 级别是指一个事务开始执行时,只能“看见”已提交事务所做的修改。这种级别不会出现脏读情况,但更新丢失还是可能发生的。
以下是一个示例,演示了更新丢失的情况:
-- session1
BEGIN;
UPDATE users SET age = 16 WHERE name = 'Alice';
-- session2
BEGIN;
UPDATE users SET age = 20 WHERE name = 'Alice';
COMMIT;
-- session1
COMMIT;
-- 本来期望 Alice 的年龄变成 16,但最终是 20
REPEATABLE READ
REPEATABLE READ 级别是指在一个事务执行期间,多次读取同一个数据,可以读到同样的结果。这种级别解决了更新丢失的问题。在 REPEATABLE READ 级别下,只有在当前事务提交之后,才会重新获取与数据操作相关的快照。这种级别下会出现幻读(即两次查询中间有新增数据的情况),但是不会出现更新丢失和脏读的情况。MySQL 默认的隔离级别就是 REPEATABLE READ。
以下是一个示例,演示了幻读问题:
-- session1
BEGIN;
SELECT * FROM students WHERE age = 20;
-- session2
BEGIN;
INSERT INTO students (name, age) VALUES ('Bob', 20);
COMMIT;
-- session1
SELECT * FROM students WHERE age = 20;
-- 第二次查询时,新增的一条记录会让查询结果变化
SERIALIZABLE
SERIALIZABLE 是最高的隔离级别,它通过强制事务串行执行来解决幻读问题。在这种级别下,所有读都会获得共享锁,写都会获得排它锁。这样,一个事务进行读取时,另一个事务无法同时进行读取或写入操作。
以下是一个示例,演示了 SERIALIZABLE 隔离级别的效果:
-- session1
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
SELECT * FROM students WHERE age = 20;
-- session2
BEGIN;
INSERT INTO students (name, age) VALUES ('David', 20);
COMMIT;
-- session1
SELECT * FROM students WHERE age = 20;
-- 第二次查询时,新增的一条记录不会对查询结果造成影响
总结
需要根据应用场景来选择合适的隔离级别。对于数据一致性要求很高的场合,可以选择更高的隔离级别。而对于并发性要求较高的场合,可以考虑使用更低的隔离级别。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入理解MySQL事务的4种隔离级别 - Python技术站