当前位置: 首页 > 科技观察

找出没有主键的表

时间:2023-03-19 21:31:19 科技观察

本文转载自微信公众号《MySQL技术》,作者MySQL技术。转载本文请联系MySQL技术公众号。前言:在MySQL中,一般在建表时都需要一个主键。如果要求不规范,难免会有几张表没有主键。在这篇文章中,让我们一起找出没有主键的表。1、表没有主键的危害以InnoDB表为例。我们都知道在InnoDB中,表是按照主键的顺序以索引的形式存储的。这种存储方式的表称为索引组织表。InnoDB表必须有聚集索引。当有主键时,主键将作为聚簇索引;如果没有显式定义主键,InnoDB将选择一个唯一的非空索引。如果没有这样的索引,MySQL会自动生成一个隐含字段作为InnoDB表的主键。也就是说,我们最好能显式定义主键,那么没有主键的表可能会造成什么危害呢?首先,没有主键就意味着不能使用主键索引,可能会影响查询效率。其次,对维护不友好。比如当你想升级到MGR集群或者使用一些开源工具时,你会要求表有主键。还有一点,对于没有主键的表的批量更新或删除,非常容易造成主从延时过长。这里顺便提一下,当主库更新或删除大量没有主键的表(尤其是没有主键、没有索引的表)时,从库会经历巨大的主从延迟,甚至会被卡住了,无法执行。别问我怎么知道的,前段时间就认识了。出现这种情况的现象是从库的延迟不断增加,而主库正在执行的binlogpos位置不变。这时候需要去主库分析一下从库卡住的binlogpos位置,发现是针对某一个没有主键表的操作。如果此时想尽快赶上从库,可以手动设置忽略表的同步,处理SQL如下:#假设是testtb表造成主从延迟,您可以忽略数据库同步mysql>STOPSLAVESQL_THREAD;QueryOK,0rowsaffected(0.00sec)mysql>CHANGEREPLICATIONFILTERREPLICATE_IGNORE_TABLE=(db.testtb);QueryOK,0rowsaffected(0.00sec)mysql>STARTSLAVESQL_THREAD;QueryOK,0rowsaffected(0.01sec)之后同步,忽略表库很快就会赶上主库。以后可以给表加一个主键,然后手动同步取消忽略。2.查找没有主键的表言归正传,当我们的数据库实例中有很多表时,我们应该如何查找是否存在没有主键的表呢?你无法一一找到它们。你可能会聪明地想到它。你可以从MySQL内置的系统表中找到,因为我们所有的建表信息都保存在系统库information_schema中。下面的SQL可以找到没有主键的表:#Findalibrary中没有主键的表(有唯一键没有主键的表也会被找到)SELECTt1.table_schema,t1.table_nameFROMinformation_schema.TABLESt1LEFTOUTERJOINinformation_schema.TABLE_CONSTRAINTSt2ONt1.table_schema=t2.TABLE_SCHEMAANDt1.table_name=t2.TABLE_NAMEANDt2.CONSTRAINT_NAMEIN('PRIMARY')WHEREt2.table_nameISNULLANDt1.table_type='BASETABLE'ANDt1.TABLE_SCHEMA='testdb';#查找整个实例中没有主键的表SELECTt1.table_schema,t1.table_nameFROMinformation.INBLESchemaOUTBLEschema。TABLE_CONSTRAINTSt2ONt1.table_schema=t2.TABLE_SCHEMAANDt1.table_name=t2.TABLE_NAMEANDt2.CONSTRAINT_NAMEIN('PRIMARY')WHEREt2.table_nameISNULLANDt1.table_type='BASETABLE'ANDt1.TABLE_SCHEMANOTIN('information_schema','performance,'mysql')一个主键,下一步就是给表添加一个主键。无论是使用自增id、uuid,还是其他算法生成的主键字段,都建议在表中添加主键。以自增id为例,我们可以这样为没有主键的表添加主键:PRIMARYKEYFIRST;主键的SQLSELECTCONCAT('ALTERTABLE',t1.table_schema,'.',t1.table_name,'ADDCOLUMNinc_idINTUNSIGNEDNOTNULLauto_incrementCOMMENT\'自增主键\'PRIMARYKEYFIRST;')FROMinformation_schema.TABLESt1LEFTOUTERJOINinformation_schema.TABLE_CONSTRAINTSt2ONt1.table_schema=t2.TABLE_SCHEMAANDt1.table_name=t2.TABLE_NAMEANDt2.CONSTRAINT_NAMEIN('PRIMARY')WHEREt2.table_nameISNULLANDt1.table_type='BASETABLE'ANDt1.TABLE_SCHEMANOTIN('information_schema','performance_schema','mysql','sys');总结:本文主要介绍可能存在的危害以及如何判断是否存在没有主键的表。本文中部分SQL是根据系统表查找的,大家可以保存在自己的环境中试试看。MySQL中的表仍然必须具有主键。人要有自己的见解,表也要有主键!