Mysql引用解释说,无法产生幻影读取,因为它利用快照进行一致的非锁定读取。(A consistent read means that InnoDB uses multi-versioning to present to a query a snapshot of the database at a point in time.)
我知道这意味着其他会话的任何写操作都不能违反当前事务的读取。(如果我只在会话上使用'select‘查询。)请注意,for update子句是不可能的。)
我使用了几个where子句来测试这一点,比如'where id=10‘或'where id>10',并检查了其他会话的写操作的任何效果。如上文所述,结果是一致的。
但是,如果我有大量的数据呢?“快照”可能很大,如下所示,这可能会导致“内存不足”问题,尽管我只查询一行(例如id = 10)。
因此,我的问题是“在MySQL中,如何准确地实现快照以防止出现任何问题?”(包括OOM,我说过)。
附注:我使用的MySQL版本是8.0
发布于 2022-11-10 16:58:54
MVCC中的快照不是RAM中数据的完整副本。创建快照所需的时间太长,而且正如您所认为的,在某些情况下,它将比可用的RAM更大。所以不是这样的。
每行版本都存储创建该行的事务id。事务的快照使用它来检查它是否可以“看到”该行版本。如果行版本太新,即它是在快照启动后提交的,那么您的快照不包括该行版本,因此它不会显示在查询结果中。这种方式在启动事务时几乎立即创建“快照”,因为不需要复制任何内容。
如果其他会话更新或删除行,则必须保留快照可以看到的行版本,以防您试图运行查询,将该行的旧版本视为其事务的一部分。因此,存储了多个版本的行。这不会导致OOM,因为行版本存储在磁盘上。
这意味着,由于数据是由其他会话更新的,因此会积累行版本。一旦您的事务结束(以及任何其他需要查看它们的事务),就可以清除那些过时的行版本,但是如果您的事务运行时间很长而没有完成提交或回滚,累积行版本的数量就会变大。它仍然不会导致OOM,但它会导致磁盘上表空间的扩展。
有关更多信息,请阅读以下内容:https://dev.mysql.com/doc/refman/8.0/en/innodb-multi-versioning.html
https://stackoverflow.com/questions/74391234
复制相似问题