为什么MySQL InnoDB比MyISAM更依赖于良好的主键设计?

P粉602998670

P粉602998670

2026-06-17

910人浏览

原创

innodb必须有聚簇索引,无显式主键时会自动生成6字节隐藏row_id作为聚簇索引键,该row_id为全局共享、互斥锁保护的计数器,高并发下易引发锁争用、页分裂、二级索引膨胀及主从复制异常;myisam则无需主键,索引与数据分离,插入即追加,无此类问题。

为什么mysql innodb比myisam更依赖于良好的主键设计?

InnoDB的聚簇索引强制绑定主键

InnoDB把数据和主键索引存在一起,也就是“聚簇索引”——PRIMARY KEY直接决定物理存储顺序。没有显式主键时,InnoDB会偷偷生成一个隐藏的row_id字段(6字节整型)作为聚簇索引键,但这个row_id是全局共享、带互斥锁的计数器,多张无主键表并发插入就会卡住。

而MyISAM完全不依赖主键:它用独立的.myd存数据、.myi存索引,索引叶子节点只存数据文件偏移量,有没有主键、主键是不是自增,对底层结构没影响。

  • MyISAM查SELECT COUNT(*) FROM t直接读内存变量,快且稳定
  • InnoDB必须全表扫描或采样估算,因为没全局行数缓存
  • InnoDB删数据后空间不一定回收,而MyISAM能自动整理碎片(OPTIMIZE TABLE

自增主键能避免B+树页分裂

InnoDB插入新行时,如果主键是AUTO_INCREMENT,新记录总追加在B+树最右叶子页末尾;但若主键是UUID或业务时间戳等随机值,数据就散落在各处,频繁触发页分裂、合并,导致:

  • 写放大:一次插入可能引发多次磁盘页写入
  • 填充率下降:页平均利用率从70%+掉到50%以下,磁盘空间浪费明显
  • 缓冲池失效:innodb_buffer_pool缓存的页很快被踢出,命中率骤降

MyISAM没这个问题——它的索引不控制数据物理位置,插入就是追加到.myd文件末尾,再更新索引指针。

二级索引存储主键值,主键大小直接影响索引体积

InnoDB所有二级索引(非主键索引)的叶子节点存的不是行地址,而是PRIMARY KEY的值。这意味着:

MySQL(Linux)
MySQL(Linux)

MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。

下载
  • 主键是BIGINT(8字节),每个二级索引项就多占8字节;1000万行,单个二级索引就多占约76MB
  • 主键是CHAR(36)的UUID,二级索引体积直接翻几倍,B+树层级变深,查询要多走1–2层节点
  • MyISAM二级索引叶子节点存的是.myd文件偏移量(固定4或8字节),跟主键类型完全无关

这也是为什么ALTER TABLE t ADD PRIMARY KEY (id)后,SHOW INDEX FROM t里所有Key_length值会突增——它真正在索引里存了。

无主键表在高并发下会暴露全局锁瓶颈

当InnoDB表没定义主键,又没合适的UNIQUE NOT NULL列时,它只能靠dict_sys.row_id生成隐式主键。这个计数器:

  • 所有无主键表共用一个mutex保护
  • 每分配256个row_id就要刷一次redo log,引发IO毛刺
  • 在OLTP场景下,几张无主键表同时插入,show engine innodb status里能看到大量ROW OPERATIONS等待

MyISAM压根没这机制——它连事务都没有,插入就是纯文件追加,锁粒度是整张表,但至少不争抢一个全局ID生成器。

真正麻烦的不是“能不能用”,而是问题往往延迟暴露:小流量测不出,一上生产,写入吞吐卡在几百TPS,排查时才发现information_schema.columns里查不到PRI,而information_schema.tables里那张表正安静地躺在“无主键”名单里。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

mysql

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
mysql修改数据表名
mysql修改数据表名

MySQL修改数据表:1、首先查看数据库中所有的表,代码为:‘SHOW TABLES;’;2、修改表名,代码为:‘ALTER TABLE 旧表名 RENAME [TO] 新表名;’。php中文网还提供MySQL的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

1118

6

MySQL创建存储过程
MySQL创建存储过程

存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数使用的语句分别为CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句调用存储过程智能用输出变量返回值。函数可以从语句外调用(通过引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。php中文网还提供MySQL创建存储过程的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.21

754

5

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

472

5

mysql密码忘了怎么查看
mysql密码忘了怎么查看

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql密码忘了怎么办呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.19

1355

5

mysql创建数据库
mysql创建数据库

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql怎么创建数据库呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.25

1879

4

mysql默认事务隔离级别
mysql默认事务隔离级别

MySQL是一种广泛使用的关系型数据库管理系统,它支持事务处理。事务是一组数据库操作,它们作为一个逻辑单元被一起执行。为了保证事务的一致性和隔离性,MySQL提供了不同的事务隔离级别。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.08

617

3

sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.11

2223

4

mysql忘记密码
mysql忘记密码

MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。那么忘记mysql密码我们该怎么解决呢?php中文网给大家带来了相关的教程以及其他关于mysql的文章,欢迎大家前来学习阅读。

2023.08.14

1943

7

mysql事务隔离级别
mysql事务隔离级别

mysql规范中定义了四种事务隔离级别,不同的隔离级别对事务的处理有所不同。本专题为大家提供mysql事务隔离级别相关的文章内容,大家可以免费体验。

2023.08.16

2374

11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 124人学习

使用phpenv集成环境安装极致CMS
使用phpenv集成环境安装极致CMS

共2课时 | 224人学习

phpEnv手册
phpEnv手册

共0课时 | 0人学习