直接查 information_schema.tables 的 table_rows 不准,因其为估算值且 innodb 下不实时更新;应改用 select count(*) 获取精确行数,但需注意大表性能、权限、特殊字符表名等问题。

直接查 information_schema.tables 为什么不准?
因为 TABLE_ROWS 是估算值,InnoDB 引擎下它不实时更新,尤其在频繁增删后偏差可能极大(比如显示 100 行,实际是 5000 行)。MyISAM 虽然相对准些,但也不保证绝对一致。所以生产环境不能依赖这个字段做精确统计。
用 SELECT COUNT(*) 才是真行数
对每个表执行 SELECT COUNT(*) FROM `table_name` 才能得到准确结果,但手动写太慢。推荐用动态 SQL 自动生成并执行:
SELECT CONCAT('SELECT ''', table_name, ''' AS table_name, COUNT(*) AS row_count FROM `', table_schema, '`.`', table_name, '`;')
FROM information_schema.tables
WHERE table_schema = 'your_database_name' AND table_type = 'BASE TABLE';
把上面结果复制出来批量执行,或者用存储过程循环调用——注意大表会锁表、拖慢查询,建议在低峰期跑。
怎么避免 COUNT(*) 卡住整个库?
大表(千万级以上)的 COUNT(*) 可能持续几秒甚至几分钟,期间占用资源、影响写入。可以考虑:
- 加
SQL_NO_CACHE避免被查询缓存干扰(MySQL 8.0+ 已移除,但 5.7 还有效) - 用
EXPLAIN看是否走了主键索引(InnoDB 的COUNT(*)通常走聚簇索引,但如果有 WHERE 条件或非空唯一索引,行为会变) - 对超大表,改用采样估算:比如
SELECT COUNT(*) * 10 FROM tbl WHERE id % 10 = 0,误差可控且快得多
自动化脚本里别漏掉 table_schema 和权限检查
生成语句时必须显式带上 table_schema,否则跨库执行会出错;另外执行用户得有对应库所有表的 SELECT 权限,否则遇到某个表就中断。常见报错是 ERROR 1142 (42000): SELECT command denied to user,不是语法问题,是权限不够。
真正麻烦的是那些带特殊字符的表名(比如含连字符、空格),要用反引号包裹,动态拼接时容易漏掉——一出错就是语法错误,得逐个检查生成的 SQL 是否合法。











