揪出那个无主键的表

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 在 MySQL 中,建表时一般都会要求有主键。若要求不规范难免会出现几张无主键的表,本篇文章让我们一起揪出那个无主键的表。

1.无主键表的危害


以 InnoDB 表为例,我们都知道,在 InnoDB 中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织表。一张 InnoDB 表必须有一个聚簇索引,当有主键时,会以主键作为聚簇索引;如果没有显式定义主键,InnoDB 会选择一个唯一的非空索引代替。如果没有这样的索引,则 MySQL 自动为 InnoDB 表生成一个隐含字段作为主键。


也就是说,最好我们可以显式定义主键,那么无主键表可能会产生哪些危害呢?首先没有主键就意味着无法用到主键索引,可能影响查询效率。其次是对维护不友好,比如想升级为 MGR 集群或使用某些开源工具时,都会要求表要有主键。还有一点,对于无主键的表批量更新或删除,极易引起很长时间的主从延迟。


这里也顺便提下,当主库对于无主键表(特别是既无主键又无索引的表)大量更新或删除时,从库会发生极大的主从延迟,甚至会一直卡着执行不下去,别问我怎么知道的,前段时间遇到过。发生这种情况的现象是从库延迟不断增大,且正在执行的主库 binlog pos 位点一直不变,这个时候需要去主库解析下从库卡着的 binlog pos 位点,发现是对某个无主键表的操作,这时若想从库尽快赶上,可以手动设置下忽略该表的同步,处理 SQL 如下:

# 假设检查发现是 testtb 表导致了主从延迟 可以再从库忽略该表的同步
mysql> STOP SLAVE SQL_THREAD;
Query OK, 0 rows affected (0.00 sec)
mysql> CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE = (db.testtb);
Query OK, 0 rows affected (0.00 sec)
mysql> START SLAVE SQL_THREAD;
Query OK, 0 rows affected (0.01 sec)

忽略掉该表的同步后,从库很快就会追上主库了。后续可以为该表增加主键,然后再手动同步下并解除忽略即可。


2.找到无主键的表


言归正传,当我们的数据库实例中有好多好多张表时,又应该如何查找是否有无主键的表呢?总不能一个个找吧,聪明的你可能想到了,可以从 MySQL 自带的系统表中查找,因为我们的所有建表信息都存储在系统库 information_schema 中。下面 SQL 可以查找出无主键的表:

# 查找某个库中无主键的表(有唯一键无主键的表也会被查出)
SELECT
    t1.table_schema,
    t1.table_name
FROM
    information_schema.TABLES t1
LEFT OUTER JOIN information_schema.TABLE_CONSTRAINTS t2 ON t1.table_schema = t2.TABLE_SCHEMA
AND t1.table_name = t2.TABLE_NAME
AND t2.CONSTRAINT_NAME IN ('PRIMARY')
WHERE
    t2.table_name IS NULL
AND t1.table_type = 'BASE TABLE'
AND t1.TABLE_SCHEMA = 'testdb';
# 查找整个实例中无主键的表
SELECT
    t1.table_schema,
    t1.table_name
FROM
    information_schema.TABLES t1
LEFT OUTER JOIN information_schema.TABLE_CONSTRAINTS t2 ON t1.table_schema = t2.TABLE_SCHEMA
AND t1.table_name = t2.TABLE_NAME
AND t2.CONSTRAINT_NAME IN ('PRIMARY')
WHERE
    t2.table_name IS NULL
AND t1.table_type = 'BASE TABLE'
AND t1.TABLE_SCHEMA NOT IN (
    'information_schema',
    'performance_schema',
    'mysql',
    'sys'
);

找到了无主键的表,下一步就是为表新增主键了,无论你使用自增 id ,uuid ,或其他算法生成的主键字段,都建议为表新增主键。以自增 id 为例,我们可以为无主键的表这样新增主键:

# 为表 tb1 新增自增ID字段作为主键
ALTER TABLE tb1 ADD COLUMN inc_id INT UNSIGNED NOT NULL auto_increment COMMENT '自增主键' PRIMARY KEY FIRST;
# 查找到的无主键表 拼接出新增主键的SQL
SELECT
CONCAT('ALTER TABLE ',t1.table_schema,'.',t1.table_name,' ADD COLUMN inc_id INT UNSIGNED NOT NULL auto_increment COMMENT \'自增主键\' PRIMARY KEY FIRST;')
FROM
    information_schema.TABLES t1
LEFT OUTER JOIN information_schema.TABLE_CONSTRAINTS t2 ON t1.table_schema = t2.TABLE_SCHEMA
AND t1.table_name = t2.TABLE_NAME
AND t2.CONSTRAINT_NAME IN ('PRIMARY')
WHERE
    t2.table_name IS NULL
AND t1.table_type = 'BASE TABLE'
AND t1.TABLE_SCHEMA NOT IN (
    'information_schema',
    'performance_schema',
    'mysql',
    'sys'
) ;


总结:


本篇文章主要介绍了无主键表可能会产生的危害及如何查找是否存在无主键的表。文中的一些 SQL 都是根据系统表来查找的,各位可以保存下到自己的环境试试看哦。MySQL 中的表还是强制要求有主键才好,人要有主见,表也要有主键!

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
存储 缓存 IDE
VirtualBox实现共享剪贴板
VirtualBox实现共享剪贴板
670 0
|
算法 Go
Golang限流器time/rate正确打开姿势
本文详细探讨了 Go 语言限流工具 `golang.org/x/time/rate` 包下的 `Limiter` 类,并通过示例展示了如何使用该工具实现 QPS 限流功能。作者深入分析了 `Limiter` 的内部工作机制,揭示了其独特的算法设计,并指出了在动态调整限流参数时可能遇到的问题及解决方法。此外,还对比了该算法与传统令牌桶和滑动窗口算法的区别,总结了其优缺点。最后,作者给出了修正限流问题的具体代码示例。
202 0
Golang限流器time/rate正确打开姿势
|
存储 关系型数据库 MySQL
MySQL8 中文参考(二十四)(2)
MySQL8 中文参考(二十四)
191 1
|
编解码
vue3+element表格调用后台接口实现Excel导出功能以及导出乱码问题解决
vue3+element表格调用后台接口实现Excel导出功能以及导出乱码问题解决
1175 0
|
机器学习/深度学习 存储 测试技术
【YOLOv8改进】 YOLOv8 更换骨干网络之 GhostNet :通过低成本操作获得更多特征 (论文笔记+引入代码).md
YOLO目标检测专栏探讨了卷积神经网络的创新改进,如Ghost模块,它通过低成本运算生成更多特征图,降低资源消耗,适用于嵌入式设备。GhostNet利用Ghost模块实现轻量级架构,性能超越MobileNetV3。此外,文章还介绍了SegNeXt,一个高效卷积注意力网络,提升语义分割性能,参数少但效果优于EfficientNet-L2。专栏提供YOLO相关基础解析、改进方法和实战案例。
解决 Idea 2020.1.1 内存占用过高问题
解决 Idea 2020.1.1 内存占用过高问题
463 0
|
SQL 数据采集 算法
Mysql主从同步及主从同步延迟解决方案
Mysql主从同步及主从同步延迟解决方案
800 0
Mysql主从同步及主从同步延迟解决方案
|
Ubuntu API 数据库
kong网关插件开发初探
kong插件开发初探
731 0
|
Java 程序员 领域建模
领域建模:分清问题域和问题解决域(下)
领域建模:分清问题域和问题解决域(下)
1048 0
领域建模:分清问题域和问题解决域(下)
|
缓存 Linux Python
Centos后台运行python程序
Centos后台运行python程序
449 0