я недавно обновился с mySQL 5.6.34 -> 8.0.16 (на macOS 10.14.5) и заметил очень странное поведение с количеством строк, возвращаемым из «SHOW TABLE STATUS», а также с количеством строк в таблице «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. я знаю о проблемах с точным подсчетом строк с использованием таблиц ИнноБД, но это все таблицы MyISAM, которые всегда должны показывать правильное количество строк. любая помощь приветствуется. Благодарю.
Таблицы информационной схемы претерпели значительные изменения несовместимые изменения в MySQL 8 с введением глобальный словарь данных:
Previously, INFORMATION_SCHEMA queries for table statistics in the STATISTICS and TABLES tables retrieved statistics directly from storage engines. As of MySQL 8.0, cached table statistics are used by default.
Кэш управляется системной переменной information_schema_stats_expiry
:
Some INFORMATION_SCHEMA tables contain columns that provide table statistics:
[...] TABLES.TABLE_ROWS [...]
Those columns represent dynamic table metadata; that is, information that changes as table contents change.
By default, MySQL retrieves cached values for those columns from the mysql.index_stats and mysql.table_stats dictionary tables when the columns are queried, which is more efficient than retrieving statistics directly from the storage engine. If cached statistics are not available or have expired, MySQL retrieves the latest statistics from the storage engine and caches them in the mysql.index_stats and mysql.table_stats dictionary tables. Subsequent queries retrieve the cached statistics until the cached statistics expire.
[...]
To update cached values at any time for a given table, use ANALYZE TABLE.
To always retrieve the latest statistics directly from the storage engine and bypass cached values, set information_schema_stats_expiry to 0.
Это соответствует вашему поведению.
Вы можете установить information_schema_stats_expiry
глобально на 0 или для каждого сеанса, когда вам нужна точная статистика.