首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
01 | 基础架构:一条SQL查询语句是如何执行的?
02 | 日志系统:一条SQL更新语句是如何执行的?
03 | 事务隔离:为什么你改了我还看不见?
04 | 深入浅出索引(上)
05 | 深入浅出索引(下)
06 | 全局锁和表锁 :给表加个字段怎么有这么多阻碍?
07 | 行锁功过:怎么减少行锁对性能的影响?
08 | 事务到底是隔离的还是不隔离的?
09 | 普通索引和唯一索引,应该怎么选择?
10 | MySQL为什么有时候会选错索引?
11 | 怎么给字符串字段加索引?
12 | 为什么我的MySQL会“抖”一下?
13 | 为什么表数据删掉一半,表文件大小不变?
14 | count(*)这么慢,我该怎么办?
15 | 答疑文章(一):日志和索引相关问题
16 | “order by”是怎么工作的?
17 | 如何正确地显示随机消息?
18 | 为什么这些SQL语句逻辑相同,性能却差异巨大?
19 | 为什么我只查一行的语句,也执行这么慢?
20 | 幻读是什么,幻读有什么问题?
21 | 为什么我只改一行的语句,锁这么多?
22 | MySQL有哪些“饮鸩止渴”提高性能的方法?
23 | MySQL是怎么保证数据不丢的?
24 | MySQL是怎么保证主备一致的?
25 | MySQL是怎么保证高可用的?
26 | 备库为什么会延迟好几个小时?
27 | 主库出问题了,从库怎么办?
28 | 读写分离有哪些坑?
29 | 如何判断一个数据库是不是出问题了?
30 | 答疑文章(二):用动态的观点看加锁
31 | 误删数据后除了跑路,还能怎么办?
32 | 为什么还有kill不掉的语句?
33 | 我查这么多数据,会不会把数据库内存打爆?
34 | 到底可不可以使用join?
35 | join语句怎么优化?
36 | 为什么临时表可以重名?
37 | 什么时候会使用内部临时表?
38 | 都说InnoDB好,那还要不要使用Memory引擎?
39 | 自增主键为什么不是连续的?
40 | insert语句的锁为什么这么多?
41 | 怎么最快地复制一张表?
42 | grant之后要跟着flush privileges吗?
43 | 要不要使用分区表?
44 | 答疑文章(三):说一说这些好问题
45 | 自增id用完怎么办?
当前位置:
首页>>
技术小册>>
MySQL 实战 45 讲
小册名称:MySQL 实战 45 讲
### 20 | 幻读是什么,幻读有什么问题? 在深入探讨MySQL数据库的高级特性时,事务的隔离级别及其引发的问题成为了不可忽视的重要话题。其中,“幻读”(Phantom Reads)作为事务隔离性中的一个复杂现象,对于理解数据库并发控制机制至关重要。本章节将详细解析幻读的定义、产生原因、造成的影响,以及在不同隔离级别下如何处理和避免幻读问题。 #### 一、幻读的定义 幻读,顾名思义,是指在同一事务中,第二次读取同一范围的数据时,由于其他并发事务的插入或删除操作,导致出现了第一次读取时未出现的新行或某些行不再可见的现象。这种现象违背了事务的隔离性原则,使得事务在逻辑上看起来像是“看到了”不存在的数据变化。 具体来说,幻读通常发生在以下场景: - **SELECT ... WHERE** 查询操作:在一个事务中,两次执行相同的查询条件,但由于其他事务的插入操作,导致第二次查询结果中包含了第一次查询时不存在的行。 - **UPDATE/DELETE** 操作:在基于某些条件执行更新或删除操作时,如果其他事务在这些操作执行期间插入了满足条件的新行,那么这些新行可能会被意外地包括在操作范围内,或者逃脱了操作的影响,这取决于具体的SQL语句和数据库的行为。 #### 二、幻读的产生原因 幻读的产生,根本原因在于数据库事务的并发执行以及不同隔离级别对并发控制的宽松程度不同。在较低的隔离级别下(如READ UNCOMMITTED和READ COMMITTED),数据库系统为了提升性能,允许一定程度的数据“脏读”或“不可重复读”,这也为幻读的出现提供了土壤。 - **READ UNCOMMITTED(读未提交)**:在此隔离级别下,一个事务可以读取到另一个事务未提交的数据,这自然无法避免幻读,因为未提交的数据随时可能因回滚而消失,或者因提交而变为可见。 - **READ COMMITTED(读已提交)**:虽然此级别保证了只能读取到已提交的数据,避免了脏读,但它仍然允许一个事务在两次查询之间,其他事务可以插入新行,从而导致幻读。 #### 三、幻读的问题 幻读问题的存在,直接影响了数据库事务的完整性和一致性,具体体现在以下几个方面: 1. **数据一致性问题**:幻读破坏了事务的隔离性,使得事务在逻辑上不能确保所操作的数据集合在事务开始到结束期间保持一致。 2. **业务逻辑错误**:在依赖特定数据集合完整性的业务逻辑中,幻读可能导致错误的业务决策或数据处理结果。 3. **并发控制难度增加**:为了避免幻读,需要采用更严格的隔离级别或额外的并发控制机制,这会增加系统的复杂性和开销。 #### 四、避免幻读的方法 为了有效避免幻读问题,可以采取以下几种策略: 1. **使用更高的隔离级别**: - **REPEATABLE READ(可重复读)**:MySQL的默认隔离级别。在此级别下,虽然能防止不可重复读,但标准SQL规范中并不保证完全避免幻读。然而,MySQL通过多版本并发控制(MVCC)和间隙锁(Gap Locks)的实现,实际上在大多数场景下防止了幻读。 - **SERIALIZABLE(可串行化)**:这是最高的隔离级别,通过强制事务串行执行来避免一切并发问题,包括幻读。但此级别的性能开销极大,通常不推荐在生产环境中使用。 2. **显式锁定**: - 在执行关键操作前,使用`SELECT ... FOR UPDATE`语句显式锁定需要操作的数据行及其周围的间隙,从而防止其他事务插入新行。但这种方法需要谨慎使用,因为它会阻塞其他事务的并发执行。 3. **应用层控制**: - 在应用层面实现更复杂的逻辑,以检测和处理潜在的幻读情况。例如,通过版本号、时间戳等方式标记数据,确保在事务处理过程中数据的一致性。 4. **使用快照隔离**: - 快照隔离(Snapshot Isolation)是一种介于可重复读和可串行化之间的隔离级别,它通过为每个事务提供数据的一个时间点快照来避免幻读,同时保持较高的并发性能。 #### 五、总结 幻读作为数据库事务并发控制中的一个重要问题,其理解和处理对于确保数据库应用的稳定性和可靠性至关重要。通过选择合适的隔离级别、使用显式锁定、应用层控制或采用快照隔离等技术手段,可以有效地避免幻读问题,保障数据的一致性和完整性。在实际应用中,应根据业务需求和系统性能要求,灵活选择适合的解决方案。
上一篇:
19 | 为什么我只查一行的语句,也执行这么慢?
下一篇:
21 | 为什么我只改一行的语句,锁这么多?
该分类下的相关小册推荐:
MySQL从入门到精通(三)
MySQL从入门到精通(五)
MySQL从入门到精通(四)
SQL零基础到熟练应用(增删改查)
MySQL必会核心问题
MySQL从入门到精通(二)
MySQL从入门到精通(一)
MySQL8.0入门与实践
细说MySQL(零基础到高级应用)