脏读

脏读,是指在不同的事务下,当前事务可以读到其他事物未提交的数据,即读到脏数据。

举个简单的例子,事务A对数据 num进行了更新,使其从1变为2,随后,事务B读取了 num,读取到的值为2,由于某种原因,事务A回滚了当前事务,此时,事务B读到的,就是事务A没有提交的数据,这就是脏读。

事务A事务B结果
SELECT t.num FROM t WHERE t.id = 1 1
BEGIN
UPDATE t SET t.num = 2 WHERE t.id = 1
SELECT t.num FROM t WHERE t.id = 12
ROLLBACK
SELECT t.num FROM t WHERE t.id = 11

不可重复读

不可重复读,是指在一个事务中多次读取同一数据集合。在这个事务没有结束时,在另一个事务中同样访问了这个数据集合,并且进行了一些DML操作。在第一个事务中,两次读取分别在另一个事务进行DML操作之前和之后,两次读取的数据不一致,此时这种情况被称为不可重复读

举个例子,事务A第一次读取数据 num,此时为1,随后事务B将 num的值修改为2,事务A再次读取 num,读取到的值为2,此时出现了两次读取不一致的情况,这就是不可重复读。

事务A事务B结果
SELECT t.num FROM t WHERE t.id = 1 1
UPDATE t SET t.num = 2 WHERE t.id = 1
SELECT t.num FROM t WHERE t.id = 1 2

幻读

幻读有点不好描述,直接举个例子吧,事务A需要查询两次同一范围的数据,比如数据量 count(*),在两次查询之间,事务B插入了一条数据,导致事务A两次查询的结果不一致,后一次读到了前一次没有看到的行,就像幻觉那样,这种情况成为幻读。幻读和不可重读读类似,但是幻读强调的是集合的增江,而不是单条数据的更新。

事务A事务B结果
SELECT COUNT(*) FROM t 3
INSERT INTO t (num) VALUES (1)
SELECT COUNT(*) FROM t 4

四种隔离级别

读未提交

读未提交(Read Uncommitted),是最低的隔离级别,所有的事务都可以看到其他未提交的事务的执行结果。不能解决脏读,不可可重复读,幻读,所以很少应用于实际项目。

读已提交

读已提交(Read Committed), 在该隔离级别下,一个事务的更新操作结果只有在该事务提交之后,另一个事务才可能读取到同一笔数据更新后的结果。可以防止脏读,但是不能解决可重复读和幻读的问题。

可重复读

可重复读(Repeatable Read),MySQL默认的隔离级别。在该隔离级别下,一个事务多次读同一个数据,在这个事务还没结束时,其他事务不能访问该数据(包括了读写),这样就可以在同一个事务内两次读到的数据是一样的。可以防止脏读、不可重复读、不过还是会出现幻读。

串行化

串行化(Serializable),这是最高的隔离级别。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。在这个级别,可以解决上面提到的所有并发问题,但可能导致大量的超时现象和锁竞争,通常不会用这个隔离级别。

最后修改:2022 年 04 月 16 日
如果觉得我的文章对你有用,请随意赞赏