我需要获取表(InnoDB)的最后一个id(主键),为此,我执行以下查询:
SELECT (SELECT `AUTO_INCREMENT` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = 'mySchema' AND `TABLE_NAME` = 'myTable') - 1;
返回错误的AUTO_INCREMENT。问题是除非我运行以下查询,否则information_schema的TABLES表不会使用当前值更新:
ANALYZE TABLE `myTable`;
为什么MySQL不会自动更新information_schema,我该如何解决此问题?
运行MySQL Server 8.0.13 X64。
答案 0 :(得分:3)
问::MySQL为什么不自动更新information_schema,我该如何解决此问题?
A: InnoDB将auto_increment值保留在内存中,并且不会将其持久化到磁盘上。
元数据查询(例如SHOW TABLE STATUS
)的行为受innodb_stats_on_metadata
和innodb_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`
让我感到困惑的是为什么我们需要检索此特定信息。我们将用它做什么?
当然,我们不会在应用程序代码中使用该值来确定分配给刚插入的行的值。不能保证最大值不是来自其他会话插入的行。并且我们有LAST_INSERT_ID()
机制来检索我们会话刚刚插入的行的值。
如果我们使用ANALYZE TABLE
刷新统计信息,那么与随后的SELECT
之间还有一段很短的时间...另一个会话可能会进入另一个INSERT
,以便从收集统计信息中获取的值在检索时可能已经“过时”。
答案 1 :(得分:2)
SELECT * FROM tbl ORDER BY insert_datetime DESC LIMIT 1;
将从“最新”插入行中获取所有数据。无需处理AUTO_INCREMENT
,不需要使用子查询,不需要ANALYZE
,不需要information_schema
,一旦拥有id后就不需要进行额外提取,等等。
是的,您确实需要在用于确定什么是“最新”的列上建立索引。是的,可以使用id
,但不能使用。 AUTO_INCREMENT
的值保证是唯一的,但没有其他。