MySQL/InnoDB和长时间运行的查询

Cha*_*ith 4 mysql sql innodb

在使用myisam引擎运行查询时,因为它不是事务性的,所以长查询(据我所知)不会影响其他查询的数据.

在InnoDB中,它警告的一件事是避免长时间的查询.当InnoDB快照时,是否会快照一切?

我之所以这么说是因为:无论出于什么原因,查询都会花费比平时更长的时间并最终回滚.同时,其他200个用户已将行更新或插入数据库.当长查询回滚时,它是否还删除其他用户所做的更新/插入?或者是涉及其他用户安全的行,除非他们越过那些被回滚的行?

jer*_*ole 5

首先,我认为作为背景阅读多版本并发控制(MVCC)作为这个答案的背景.

InnoDB实现了MVCC,这意味着它可以使用常规的非锁定读取SELECT.这不需要创建"快照",实际上InnoDB没有任何真实的快照概念作为对象.相反,数据库中的每个记录都会跟踪其自己的版本号,并维护"滚动指针"到"撤消日志"记录(可能存在或不存在),该记录将行修改为其先前版本.如果需要较旧版本的记录,则读取当前版本并遵循那些滚动指针并应用撤消记录,直到生成足够旧版本的记录.

通常,系统会不断清理这些撤消日志并重新使用它们占用的空间.

每当存在任何长时间运行的事务(注意,不一定是单个查询)时,必须保留(不清除)撤销日志,以便充分重新创建所有记录的足够旧版本以满足该事务.在非常繁忙的系统中,这些撤消日志可以非常快速地累积以消耗千兆字节的空间.此外,如果经常修改特定的单个记录,则将该记录还原为足够旧的版本以满足查询可能需要非常多的撤消日志应用程序(数千).

这就是让"长期运行的查询"变得昂贵且不受欢迎的原因.它们会增加磁盘空间消耗,以便将撤消日志保留在系统表空间中,并且由于撤消日志记录应用程序在读取时还原行版本,它们将表现不佳.

某些数据库实现了可以使用的最大量的撤消日志空间,一旦达到该限制,它们就会开始丢弃旧的撤消日志记录并使运行的事务无效.这会向用户生成"快照太旧"错误消息.InnoDB没有这样的限制,并且允许无限累积.