软考数据库学习中,不能把所有“两次查询结果不同”都归成同一种异常。理解不可重复读和幻读区别,要先确定读的是原有记录,还是满足某个条件的一组记录,再核对事务提交顺序。你可以结合知英教育的软考方向与备考指南整理数据库基础问题,避免只背名称。
先固定前提:读写对象与事务提交顺序
设事务甲负责查询,事务乙在两次查询之间改变数据。以下情境都要求甲的两次查询发生在同一事务中;除脏读对照外,乙的改变都已提交。例子用于解释异常现象,是否实际出现,还取决于数据库、隔离级别、读取方式等条件。
我们使用一张虚构的练习成绩表:记录21为62分,记录22为75分,记录23为58分。记录号用于识别同一条数据;“分数不低于60分”则是筛选结果集的条件。这两种读取目标不能混为一谈。

情境一:同一条记录,前后数值不同
事务甲第一次按记录号21读取,得到62分。事务乙把该记录改为66分并提交。事务甲随后再次读取记录21,得到66分。在允许这种变化被看见的条件下,这体现不可重复读:原先读过的数据被其他已提交事务改动,再读时不一致。
判断依据不是分数变大还是变小,也不是第二次执行得快慢,而是同一事务复读原有数据时,遇到了另一事务已提交的修改。如果两次查询分属两个独立事务,不能仅凭结果不同就套用这个情境。
情境二:查询条件相同,结果集多了一个成员
重新从最初的三条记录开始。事务甲按“分数不低于60分”查询,返回记录21和22。事务乙新增记录24,分数84分,并提交。事务甲再按同一条件查询,返回21、22和24。这里关注的是符合条件的一组记录发生变化,体现幻读问题。
对不可重复读和幻读区别的解释,常被压缩成“前者值变,后者数量变”。这个记法能帮助入门,但不够完整:结果集是否变化,不能只数行数,还要看成员是谁。

数量没变,为什么仍不能说结果集没变
仍从初始数据出发。事务甲第一次查询“分数不低于60分”,返回21和22。事务乙在一个事务中把21改为55分,把23改为68分,随后提交。若甲复查时看见这些变化,结果变为22和23。前后都是两条,成员却从“21、22”换成了“22、23”。
这个反例说明,官方定义中的“满足查询条件的记录集合变化”比“数量增加或减少”更完整。若甲还逐条读取相关记录,也可能同时观察到其他变化;不能脱离具体读操作,强行把所有并发现象当成互不重叠的标签。
在知英教育梳理这类学习问题时,可以先画读取对象和事务提交顺序,再讨论异常名称。把“没看提交”“只看条数”“漏掉同一事务前提”分开,比反复记一句口诀更容易定位错误。

先排除脏读,再讨论复读与结果集
如果事务乙尚未提交,甲已经读到了乙写入的数据,首先要识别脏读。特别是乙随后回滚的情境,关键是甲读到了未提交数据,而不是仅仅“两次结果不同”。它与前面已经提交后再复查的条件不同。
标准名称与具体数据库表现分别看
隔离级别不能仅凭名称推断全部实现细节。PostgreSQL 18文档明确区分SQL标准允许的现象与本产品保证:其Repeatable Read不允许幻读,比标准最低要求更强。
MySQL 8.4的InnoDB文档则说明,Repeatable Read下同一事务的普通非锁定查询读取首次一致性读建立的快照;锁定读、更新与删除按相应规则处理记录或索引范围。混用读取方式时,不能把一种查询的表现推到所有操作。学习概念时应先按题目给出的前提判断;讨论具体系统时,再核对版本与官方说明。
用四项清单复盘
- 两次读取是否属于同一事务?
- 另一事务的写入已经提交,还是尚未提交?
- 比较的是原先读过的数据,还是相同条件下的记录集合?
- 结果集的成员是否变化,而不只是行数是否变化?
复习不可重复读和幻读区别时,可以用这四项为自己的判断写出依据。需要安排数据库章节学习,可在咨询软考学习安排时说明目标资格、已有基础和错题类型。知英教育可据此梳理学习顺序;具体考试范围与开考资格以当期官方资料为准。
资料核对日期:2026年11月1日。依据:PostgreSQL 18官方文档:13.2 Transaction Isolation,异常定义、隔离表与Read Committed;MySQL 8.4官方文档:17.7.2.1 Transaction Isolation Levels。本文例句、数字和情境为原创辅助说明,不作为官方试题或新增考点证明。

