MySQL查询执行中字段能否变更?缓存B表数据的代码是否冗余?
咱们来好好捋一捋你的问题——先分MyISAM和InnoDB两种场景拆解,再说说那段缓存逻辑到底有没有必要:
MyISAM引擎时期的情况
MyISAM是表级锁机制,而且不支持事务,咱们分两点说:
- 查询期间能否更新B表?
MyISAM的读操作会加表级共享锁,写操作(比如UPDATE)需要排他锁。如果你的查询是普通SELECT(没手动加锁),当查询执行时:- 若PHP用的是默认的
mysql_store_result(也就是把整个结果集一次性拉到客户端),那查询执行完成后读锁就释放了,这时候其他会话可以更新B表,但你的结果集已经是查询时刻的完整快照了,遍历的时候数据不会变; - 若用的是
mysql_use_result(逐行从服务器取数据),读锁会一直持有到结果集遍历完毕,这时候其他会话的更新会被阻塞,直到你遍历完所有行。
- 若PHP用的是默认的
- 会不会出现同一B.id对应不同B.value的结果?
答案是不会。不管是哪种结果集获取方式,结果集里的B表数据都是查询执行时刻的状态,不会中途被更新影响,所以同一B.id的行对应的B.value肯定是一致的。
现在InnoDB引擎的情况
InnoDB支持事务,默认隔离级别是可重复读(REPEATABLE READ),这是关键:
- 查询期间能否更新B表?
InnoDB是行级锁,其他事务可以更新B表中未被当前查询锁定的行,但这不会影响你的查询结果——因为InnoDB的一致性读会让你看到事务启动时的快照(自动提交模式下,每个SELECT就是一个独立事务)。 - 会不会出现同一B.id对应不同B.value的结果?
同样不会。整个查询(包括遍历结果集的过程)看到的都是执行SELECT时的B表快照,哪怕其他事务把B表的某行改了N次,你的结果集里对应的数据都不会变。
那这段缓存逻辑到底有没有必要?
结论是:完全冗余。
不管是当年的MyISAM还是现在的InnoDB,数据库自身的机制已经保证了你的结果集里同一B.id对应的B.value是完全一致的,不会出现“同一B.id对应不同B.value”的情况。
当然,如果你后续还有其他逻辑需要复用B表的行数据,缓存可能有性能上的小优势,但单纯从“防范结果集中同一B.id数据不一致”这个目标来看,这段代码是多余的,完全可以去掉。
内容的提问来源于stack exchange,提问作者Vilx-
相关产品推荐
相关产品推荐

