MySQL 不更新 information_schema,除非我手动运行 ANALYZE TABLE `myTable`

Yan*_*rin 9 mysql innodb information-schema mysql-8.0

我需要获取表 (InnoDB) 的最后一个 id(主键),为此我执行以下查询:

SELECT (SELECT `AUTO_INCREMENT` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = 'mySchema' AND `TABLE_NAME` = 'myTable') - 1;
Run Code Online (Sandbox Code Playgroud)

它返回错误的 AUTO_INCREMENT。问题是 information_schema 的 TABLES 表未使用当前值更新,除非我运行以下查询:

ANALYZE TABLE `myTable`;
Run Code Online (Sandbox Code Playgroud)

为什么 MySQL 不自动更新 information_schema,我该如何解决这个问题?
运行 MySQL 服务器 8.0.13 X64。

spe*_*593 10

问:为什么 MySQL 不自动更新 information_schema,我该如何解决这个问题?

A: InnoDB 将 auto_increment 值保存在内存中,并且不会将其持久化到磁盘。

元数据查询(例如SHOW TABLE STATUS)的行为受innodb_stats_on_metadatainnodb_stats_persistent变量的设置影响。

https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_stats_on_metadata

每次我们查询元数据时都强制执行 ANALYZE 可能会消耗性能。

除了这些变量的设置,或者通过手动执行强制收集统计信息之外ANALYZE TABLE,我认为没有“修复”这个问题。

(我认为这主要是因为我认为这不是一个需要解决的问题。)


要获得表中 auto_increment 列的最大值,规范模式是:

 SELECT MAX(`ai_col`) FROM `myschema`.`mytable`
Run Code Online (Sandbox Code Playgroud)

让我困惑的是为什么我们需要检索这条特定的信息。我们要用它做什么?

当然,我们不会在应用程序代码中使用它来确定分配给我们刚刚插入的行的值。不能保证最高值不是来自其他会话插入的行。我们有LAST_INSERT_ID()机制来检索我们的会话刚刚插入的行的值。

如果我们使用ANALYZE TABLE刷新统计数据,那么在此和后续之间还有一小段时间SELECT......另一个会话可能会滑入另一个会话,INSERT因此我们从收集统计信息中获得的值可能在我们之前“过时”取回它。

  • 拥有合适的索引应该可以使`SELECT MAX(mycol) FROM mytable` 具有合理的性能。用例唯一的错误是有点模糊。我们需要检查我们的新(要插入)行的坐标是否在 ai_col 值最高的行坐标的 10mi 之内?如果我们必须查询表以获取坐标,那么我们可以使用类似`SELECT r.coordinate_col FROM mytable r JOIN ( SELECT MAX(t.id) AS max_id FROM mytable t ) s ON s.max_id = r.id`。 (2认同)
  • @YanKarin - 如果您使用`ORDER BY id DESC LIMIT 1`,则不需要子查询。(类似于我的回答。)您的查询(和我的变体)将返回 true/false (1/0),具体取决于它是否在 10 个距离单位内。(注意你的单位是什么。) (2认同)