脏读,不可重复读,幻读以及四种隔离级别
前言
在事务中,我们常听到脏读,不可重复读,幻读这三种概念。本文将根据例子来讨论这三种问题。同时,再依次谈谈解决上述问题的三种隔离级别。
原文地址:https://xuedongyun.cn/post/64889/
脏读
脏读的定义
脏读,又称为“读未提交”,就是事务A读取到了事务B已修改但未提交的数据
我们来看一个例子:假设age原本是13。事务B修改age后,被事务A读到了,但是事务B最后回滚了。也就是说,事务A读到了事务B修改但未提交的数据。
事务A | 事务B |
---|---|
开始事务 | 开始事务 |
修改age(从13改为23) | |
查询age(age=23) | |
commit | rollback(回滚,age实际上还是13) |
解决脏读的隔离级别
我们可以使用READ_COMMITTED
这个隔离级别来解决脏读的问题。READ_COMMITTED
要求事务A只能读取其他事务已提交的修改
1 |
不可重复读
不可重复读的定义
不可重复读,又称为“读已提交”,就是事务A中多次读取数据,读取到的结果不一样
我们来看一个例子:在事务A中,先查询了一次,age=13。此时事务B修改并提交。在事务A中,又查询了一次,此时事务B已提交,所以能成功读取,但此时age=23,已经和之前不一致了
事务A | 事务B |
---|---|
开始事务 | 开始事务 |
查询age(age=13) | |
修改age(从13改为23) | |
commit | |
查询age(age=23) | |
commit |
解决不可重复读的隔离级别
我们可以使用REPEATABLE_READ
这个隔离级别来解决脏读的问题。REPEATABLE_READ
要求事务A执行时,其他事务禁止对这个字段进行修改
1 |
这也是MySQL的默认隔离级别
幻读
幻读的定义
幻读,就是事务A前后两次读取中,事务B插入或者删除数据,从而发生的一种类似幻觉的现象
我们来看一个例子:事务A前后两次查询id=1001的用户,第一次找不到,第二次又找到了。这是因为在两次查询之间,事务B插入了新的数据。(REPEATABLE_READ
只限制了不能修改,没有限制增删)
事务A | 事务B |
---|---|
开始事务 | 开始事务 |
查询id=1001的用户,发现没找到 | |
插入id=1001的用户 | |
commit | |
查询id=1001的用户,发现又能找到了 | |
commit |
解决幻读的隔离级别
我们可以使用SERIALIZABLE
这个隔离级别来解决脏读的问题。SERIALIZABLE
要求事务A执行时,其他事务禁止对这个表进行添加、更新、删除操作
1 |
总结
三种问题
- 脏读:读到了已修改但未提交的数据
- 不可重复读:前后两次读取的结果不一样
- 幻读:之前读取存在,再读发现不存在了(或者反之亦然)
四种隔离级别
READ UNCOMMIT
:最低的级别,能读到未提交的数据READ COMMIT
:只能读修改已提交的数据- 解决:脏读
REPEATABLE READ
:读取期间,其他事务不能对该字段进行修改- 解决:脏读,不可重复读
SERIALIZABLE
:读取期间,其他事务不能对这个表进行增删改- 解决:脏读,不可重复读,幻读
- 标题: 脏读,不可重复读,幻读以及四种隔离级别
- 作者: 布鸽不鸽
- 创建于 : 2023-06-17 19:13:17
- 更新于 : 2024-01-06 18:38:04
- 链接: https://xuedongyun.cn//post/64889/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
推荐阅读
评论