Quantcast
Channel: 日々の覚書
Viewing all articles
Browse latest Browse all 582

MySQL 8.0のSHOW TABLE STATUSが全然更新されない件

$
0
0

TL;DR


空っぽのテーブルを用意する。
mysql80 111566> SHOW TABLE STATUS\G
*************************** 1. row ***************************
Name: t1
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 0
Avg_row_length: 0
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: 2019-05-16 15:41:52
Update_time: NULL
Check_time: NULL
Collation: utf8mb4_0900_ai_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
データを1万行くらい入れる。
$ for n in $(seq 1 10000) ; do mysql80 -e "INSERT INTO t1 VALUES ($n, '')" d1; done

mysql80 111566> SELECT COUNT(*) FROM t1;
+----------+
| COUNT(*) |
+----------+
| 10000 |
+----------+
1 row in set (0.00 sec)
でも SHOW TABLE STATUSの結果は変わらない。。
mysql80 111566> SHOW TABLE STATUS\G
*************************** 1. row ***************************
Name: t1
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 0
Avg_row_length: 0
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: 2019-05-16 15:41:52
Update_time: NULL
Check_time: NULL
Collation: utf8mb4_0900_ai_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
ちなみに SHOW CREATE TABLEの方の AUTO_INCREMENTの値はちゃんと増えてる。
mysql80 111566> SHOW CREATE TABLE t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`num` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`val` varchar(32) DEFAULT NULL,
UNIQUE KEY `num` (`num`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
これはMySQL 8.0.3から information_schema_stats_expiryなるオプションが増えてからの挙動で、どうも information_schema.tablesに含まれるほとんどの情報は mysql.table_statsテーブルにキャッシュされ、そのキャッシュがexpireされるまではずっとその値を使う様子( mysql.table_statsは隠れシステムテーブルなので、フツーにSQLを使っているだけだとそのテーブルは見えない)
mysql80 111566> SELECT * FROM mysql.table_stats;
ERROR 3554 (HY000): Access to data dictionary table 'mysql.table_stats' is rejected.
オプションにも書いてある通り、単位は秒でデフォルトは86400秒(= 24時間)
つまりどれだけテーブルを更新しようと、 information_schema.tablesSHOW TABLE STATUSの値は「最後に mysql.table_statsが更新されてから24時間」は全く変更されない(ように見える)
コード的には このへんでキャッシュがexpireされてるかとかそのへんを判定してて、元をたどって進んでいくと ここらへんでキャッシュを更新する処理に突入している。
(現在時刻 - キャッシュの更新時刻) > information_schema_stats_expiryになった場合はキャッシュを更新してその結果を、 information_schema_stats_expiry = 0の場合はそもそも mysql.table_statsテーブルをキャッシュとして 使わないみたいな動作になるようだ。
mysql80 111566> SET SESSION information_schema_stats_expiry= 1;
Query OK, 0 rows affected (0.01 sec)

mysql80 111566> SHOW TABLE STATUS\G
*************************** 1. row ***************************
Name: t1
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 10000
Avg_row_length: 32
Data_length: 327680
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: 10001
Create_time: 2019-05-16 15:41:52
Update_time: 2019-05-16 16:02:34
Check_time: NULL
Collation: utf8mb4_0900_ai_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
セッションスコープ, グローバルスコープが両方あるタイプの変数なので、監視用のセッションにだけ押し込んでおけばいいかと。
しかし SET_VAR構文は使えないらしいので残念。

Viewing all articles
Browse latest Browse all 582

Trending Articles