应使用information_schema.table_constraints表查询主键约束,因column_key='pri'仅标识列属性而非真实主键约束,易在分区表、临时表等场景误判;table_constraints中constraint_type='primary key'才是准确依据。

直接结论:用 information_schema.TABLE_CONSTRAINTS 关联查最稳,别信 COLUMN_KEY = 'PRI' 或 KEY_COLUMN_USAGE 的单表扫描结果——它们在分区表、临时表、视图混杂时容易漏判或误报。
为什么 COLUMN_KEY = 'PRI' 查询会失效
很多脚本依赖 INFORMATION_SCHEMA.COLUMNS 中的 COLUMN_KEY = 'PRI' 字段判断主键,但这个字段只反映“该列是否被标记为主键列”,不等于“该表有主键约束”。常见失效场景包括:
- 表有唯一非空索引(
UNIQUE NOT NULL),InnoDB 自动选它当聚簇索引,但COLUMN_KEY仍为''或UNI,不是PRI - 使用
CREATE TABLE ... AS SELECT创建的表,不带约束定义,COLUMN_KEY全为空,但实际可能有隐式主键行为(如含AUTO_INCREMENT列) - MySQL 8.0+ 对分区表的元数据处理更严格,
COLUMNS视图中父表行不展示任何COLUMN_KEY,导致误判为“无主键”
推荐查询:用 TABLE_CONSTRAINTS 精准定位缺失主键约束的表
主键是约束(CONSTRAINT),不是列属性。真正可靠的依据是 INFORMATION_SCHEMA.TABLE_CONSTRAINTS 中是否存在 CONSTRAINT_TYPE = 'PRIMARY KEY' 的记录。
以下 SQL 可一次性扫全实例(排除系统库 + 支持大表过滤):
SELECT
t.table_schema,
t.table_name,
ROUND((t.data_length + t.index_length) / 1024 / 1024 / 1024, 2) AS size_gb
FROM information_schema.tables t
LEFT JOIN information_schema.table_constraints tc
ON t.table_schema = tc.table_schema
AND t.table_name = tc.table_name
AND tc.constraint_type = 'PRIMARY KEY'
WHERE t.table_schema NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
AND t.table_type = 'BASE TABLE'
AND tc.table_name IS NULL
AND (t.data_length + t.index_length) > 5 * 1024 * 1024 * 1024
ORDER BY (t.data_length + t.index_length) DESC;
关键点:
- 必须用
tc.constraint_type = 'PRIMARY KEY'(注意字符串带空格),不是'PRIMARY'或'P' -
AND (t.data_length + t.index_length) > ...要写在WHERE,不能用HAVING,否则 MySQL 8.0+ 可能因无 GROUP BY 报错 - 过滤系统库必须写全,漏掉
sys会导致sys.x$innodb_buffer_stats_by_schema这类视图被误计入
确认某张表是否正在引发复制延迟
查出表只是第一步。要验证它是不是当前 Seconds_Behind_Master 持续飙升的元凶,得结合从库状态和 binlog 解析:
- 在从库执行
SHOW SLAVE STATUS\G,看Relay_Log_File和Exec_Master_Log_Pos是否长时间不动 - 用
mysqlbinlog解析对应位置:mysqlbinlog -v --base64-output=DECODE-ROWS relay-log-file | grep -A 5 -B 5 "table_name" - 若发现大量
UPDATE/DELETE针对同一张无主键大表,且语句里没有 WHERE 条件或仅靠非索引字段过滤,基本可锁定
此时别急着加主键——在线 DDL 可能锁表数小时。先用 CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE = (db.tbl) 临时跳过,再择机重建表。
真正危险的不是“没主键”,而是“没主键 + 大数据量 + 频繁 DML”。哪怕一张 200MB 的表,只要每天只 INSERT 几十行,也不构成复制风险。重点盯住 size_gb > 5 且 table_rows > 1e6 的组合,这类表一旦出问题,SQL 线程卡死几小时都算轻的。











