我最近从mySQL 5.6.34 -> 8.0.16(在macOS 10.14.5上)升级,我注意到从"显示表状态"返回的行计数以及"information_schema"表中的行计数非常奇怪的行为。 请考虑以下简单架构:
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `test` (`id`, `name`) VALUES
(1, 'one'),
(2, 'two'),
(3, 'three'),
(4, 'four'),
(5, 'five');
然后,当我运行以下查询时,我看到了预期的输出:
SELECT * FROM test;
+----+-------+
| id | name |
+----+-------+
| 1 | one |
| 2 | two |
| 3 | three |
| 4 | four |
| 5 | five |
+----+-------+
同样,当我运行以下查询时,我会看到预期的输出:
SELECT COUNT(*) FROM test;
+----------+
| COUNT(*) |
+----------+
| 5 |
+----------+
但是,当我然后运行以下查询时:
SHOW TABLE STATUS G
*************************** 1. row ***************************
Name: test
Engine: MyISAM
Version: 10
Row_format: Dynamic
Rows: 0
Avg_row_length: 0
Data_length: 0
Max_data_length: 281474976710655
Index_length: 1024
Data_free: 0
Auto_increment: 1
Create_time: 2019-05-30 13:56:46
Update_time: 2019-05-30 16:02:24
Check_time: NULL
Collation: utf8_unicode_ci
Checksum: NULL
Create_options:
Comment:
似乎没有行(即使有 5 行)。 同样,当我运行时,我会看到相同的结果:
SELECT table_name, table_rows FROM information_schema.tables WHERE table_schema = 'test';
+------------+------------+
| TABLE_NAME | TABLE_ROWS |
+------------+------------+
| test | 0 |
+------------+------------+
没有行? 如果我在表中添加/删除行,计数不会改变。 只有在我运行之后:
ANALYZE TABLE `test`
。我是否看到所有行计数都正确。我只在mySQL 8上看到这个。一切都在mySQL 5上按预期工作。我知道使用InnoDB表的准确行计数存在问题,但这些都是MyISAM表,它们应该始终显示正确的行数。任何帮助不胜感激。谢谢。
随着全局数据字典的引入,信息模式表在MySQL 8中经历了重大的,不兼容的变化:
以前,对 STATISTICS 和 TABLES 表中表统计信息的INFORMATION_SCHEMA查询直接从存储引擎检索统计信息。从MySQL 8.0开始,默认情况下使用缓存的表统计信息。
缓存由系统变量控制information_schema_stats_expiry
:
某些INFORMATION_SCHEMA表包含提供表统计信息的列:
[...]表。TABLE_ROWS [...]
这些列表示动态表元数据;即,随着表内容更改而更改的信息。
默认情况下,MySQL在查询列时从mysql.index_stats和mysql.table_stats字典表中检索这些列的缓存值,这比直接从存储引擎检索统计信息更有效。如果缓存的统计信息不可用或已过期,MySQL将从存储引擎中检索最新的统计信息,并将其缓存在mysql.index_stats和mysql.table_stats字典表中。后续查询将检索缓存的统计信息,直到缓存的统计信息过期。
[...]
若要随时更新给定表的缓存值,请使用分析表。
要始终直接从存储引擎检索最新统计信息并绕过缓存值,请将information_schema_stats_expiry设置为 0。
这与您的行为一致。
您可以将全局information_schema_stats_expiry
设置为 0,或者在需要准确统计信息时按会话设置。