一直在用MySQL,但今天看到一个面试问了隔离性级别感觉有点懵,一直都没有注意过,所以学习并记录了一下。
一、ACID设计原则
要讲事务的隔离性,首先要了解MySQL的ACID设计原则。
- 原子性 (Atomicity):确保事务中的所有操作要么全部成功,要么全部失败。
- 一致性 (Consistency):事务的执行必须使数据库从一个一致性状态变换到另一个一致性状态。
- 隔离性 (Isolation):并发执行的事务之间相互隔离,互不影响。
- 持久性 (Durability):一旦数据被提交,其结果是永久性的,即使系统出现故障也不会丢失。
这四个原则,实际上前三个都是跟事务相关的,即原子性、一致性、隔离性,熟悉MySQL的朋友,应该看解释就能看懂什么意思。
二、隔离级别
但隔离性又有几种级别,分别是:
- 读未提交(READ UNCOMMITTED):
- 级别最低,事务可以读取未提交的更改。
- 可能导致脏读(Dirty Read),即读取到其他事务尚未提交的数据。
- 读已提交(READ COMMITTED):
- 事务只能读取已提交的更改。
- 避免了脏读,但仍可能出现不可重复读(Non-repeatable Read),即在同一事务中两次查询结果可能不同,因为其他事务可以提交更改。
- 可重复读(REPEATABLE READ):
- 在同一事务中多次读取相同数据,总是返回相同的结果。
- 在当前事务提交之前,其他任何事务均不可以修改或删除当前事务已读取的数据
- 解决了脏读和不可重复读的问题,但可能出现幻读(Phantom Read),即在同一事务中执行查询时,数据行数可能因为其他事务的插入而不同。
- 串行化(SERIALIZABLE):
- 最高的隔离级别,事务按顺序执行,完全避免了脏读、不可重复读和幻读。
- 性能较低,因为它可能导致大量的等待和性能瓶颈,通常用于需要严格一致性的场景。
可以看到隔离级别是依次递增的,读未提交和串行化都比较好理解,但读已提交和可重复读容易出现歧义点。
三、歧义点
1、读已提交既然是只能读已提交的更改,那在本事务中未提交的更改,能读出来吗?
答:可以读出来,因为隔离性是针对不同事务之间的,在本事务中这些操作都属于同一个事务上下文。
2、可重复读的幻读是什么意思?
答:可以看到可重复读是不可修改和删除当前事务已读的数据,但是没有限制写入,所以在事务中第一次读取的数据后其他业务有插入数据,这时候再读第二次时,可能与第一次数据的数据结果不同。
四、设置隔离级别
执行以下 SQL 语句设置 MySQL 的隔离级别:
# level_name 可以是上述的任一隔离级别
SET TRANSACTION ISOLATION LEVEL level_name;全局设置隔离级别:
SET GLOBAL TRANSACTION ISOLATION = 'level_name';查看当前隔离级别
SELECT @@transaction_isolation;