![60433197d762a88cb16f2b17aa7670a0.png](https://img-blog.csdnimg.cn/img_convert/60433197d762a88cb16f2b17aa7670a0.png)
作为mysql运维开发人员,show table status命令还是比较经常用的,但是换了新版本8.0之后,似乎不大好用了,好像出问题了,更新不了表信息了,是不是有bug,我们试试吧。
环境准备,问题复现
数据库版本:mysql 8.0.19,我们新增一个空表(test),简单点,就id和name字段,建好之后
![ed7547870241e3aaf979ecc6a1720a0a.png](https://img-blog.csdnimg.cn/img_convert/ed7547870241e3aaf979ecc6a1720a0a.png)
# 第一次执行
show table status where name = 'test'
看到 Rows = 0,没问题
![926d3e6a6fdc83c9ea320bc06ff276c7.png](https://img-blog.csdnimg.cn/img_convert/926d3e6a6fdc83c9ea320bc06ff276c7.png)
这时候随便插入3条数据并提交,然后再执行一下
show table status where name = 'test'
![6c4b02e0129019e707e4cabaf710cf5e.png](https://img-blog.csdnimg.cn/img_convert/6c4b02e0129019e707e4cabaf710cf5e.png)
![c87d135bf3ba7991c5fca920155df2bb.png](https://img-blog.csdnimg.cn/img_convert/c87d135bf3ba7991c5fca920155df2bb.png)
依旧没有更新,换句话说,就是执行 SHOW TABLE STATUS 时无法及时查看到该表的最新统计信息。如果不更新的话,你肯定想,那这个命令还有什么存在的必要,或者根本就是bug。但是你可能会怀疑,然后就会去查看 mysql.innodb_table_stats 和 mysql.innodb_index_stats 两个表,却又可以看到该表的统计信息已经更新了,但是结果可能又不是你想要的,我们先看看结果
select * from mysql.innodb_table_stats where database_name ='***' and table_name ='test';
![a61404398dc01d81e87b992b73265b13.png](https://img-blog.csdnimg.cn/img_convert/a61404398dc01d81e87b992b73265b13.png)
数据更新了,但是显示只有2行数据。再看看下面
select * from mysql.innodb_index_stats where database_name ='***' and table_name ='test';
![38e72ec9a77005ab2cb25ba768dfdae7.png](https://img-blog.csdnimg.cn/img_convert/38e72ec9a77005ab2cb25ba768dfdae7.png)
这个表倒是正确了,3个ID索引记录。
什么原因及解决方法
1、因为mysql升到8.0之后。TABLES表中看到的数据是有缓存的,默认缓存时长是 86400秒(即1天),修改参数 information_schema_stats_expiry 即可调整时长。也就是说,除非cache过期了,或者手动执行 ANALYZE TABLE 更新统计信息,否则不会主动更新。
这个参数(功能)是MySQL 8.0后新增的,所以这个问题在8.0之前的版本不存在。
参数 information_schema_stats_expiry 还影响其 IFS.STATISTICS 表。
我们手工执行下表分析,在执行show table status,即可看到更新行数据了
ANALYZE TABLE test show table status where name = 'test'
![0abc8e210de414be80d3e747c717f797.png](https://img-blog.csdnimg.cn/img_convert/0abc8e210de414be80d3e747c717f797.png)
2、为什么innodb_table_stats 显示数据不正确呢?这个其实是存储引擎的关系!
就是说MyISAM表的Rows是精确值,但InnoDB表则只是大概值,甚至有可能只是真实值的40% ~ 50% 之间。这个官方文档有说明:
• Rows
The number of rows. Some storage engines, such as MyISAM, store the exact count. For other storage engines, such as InnoDB, this value is an approximation, and may vary from the actual value by as much as 40% to 50%. In such cases, use SELECT COUNT(*) to obtain an accurate count.
The Rows value is NULL for INFORMATION_SCHEMA tables.
3、我们也可以使用更改会话级别的参数来使得show table status 生效
set session information_schema_stats_expiry = 0;
看来,如果应用程序中有需要读取 table status 概要信息的时候,最好还是先手动执行 ANALYZE TABLE 或者修改参数值,也可以用下面这样的SQL:
select /* set_var(information_schema_stats_expiry = 1) */ * from information_schema.tables where table_schema='***' and table_name = 'test'
这是MySQL 8.0后新增的HINT语法。
执行以上语句之后,再执行 show table status 之后,就能实时看到更新了。