innodb必须有聚簇索引,无显式主键时会自动生成6字节隐藏row_id作为聚簇索引键,该row_id为全局共享、互斥锁保护的计数器,高并发下易引发锁争用、页分裂、二级索引膨胀及主从复制异常;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 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里那张表正安静地躺在“无主键”名单里。










