京东二面的这道题,我印象很深。面试官先抛出的是“加索引时,会锁表吗?”我当时顿了一下,因为这个问题真正要的答案不是“会”或“不会”,而是你对数据库、版本、DDL机制、锁模型的理解到了一个什么位置。后来复盘时我发现,如果只是机械背出“MySQL 5.6之后Online DDL不锁表”就能应付过去,但对面真正想听的,是你能不能讲清楚“为什么有的操作不锁、有的操作看起来卡死了、大表加索引到底该怎么落地”。这篇把那次面试之后我重新梳理的东西写全:从版本演进、Online DDL原理,到一次真实线上“假锁死”排查,再到大表加索引的工具选择和面试回答案例。
1. 这个问题的第一层答案:取决于你用的是哪个版本的MySQL
1.1 5.5及以前的真实情况:基本可以理解为锁表
MySQL 5.5时代,“给表加一个索引”并没有真正意义上的在线DDL能力。InnoDB虽然有Fast Index Creation这样的优化——添加二级索引时不需要把整张表拷贝成新表再替换,锁的范围还是会非常大。执行期间其他事务的写操作基本都要等,整张表被大粒度的锁包住,业务在这段时间内是做不了正常写入的。
如果用的是MyISAM存储引擎,那更直接,ALTER TABLE执行时会拿表的排他锁,读和写都会被挡住。早期互联网公司做表结构变更,都要挑凌晨流量最低的窗口,因为一次全表拷贝再换表可能跑几十分钟,期间业务写入中断是常态。现在很多老DBA习惯把变更放在凌晨2点到5点,这个习惯就是那个时代留下的。
1.2 5.6是真正的分水岭:Online DDL正式落地
MySQL 5.6把Online DDL从“特性预告”变成了“默认能力”。核心变化在于:ALTER TABLE在执行时需要明确选择算法和锁级别,同时也开始从机制上支持在执行阶段不阻塞业务写入。
ALTER TABLE t_order
ADD INDEX idx_user_id (user_id),
ALGORITHM=INPLACE,
LOCK=NONE;
对于“新增普通二级索引”这个操作,5.6之后是可以在INPLACE算法下,以LOCK=NONE的方式执行的。这意味着你在执行期间,业务可以继续对该表进行常规增删改查,不会被一块大锁挡住几十分钟。
1.3 版本对照:加索引时的锁行为差异
| 版本阶段 | 加普通二级索引时的表现 | 实际体验 |
|---|---|---|
| MySQL 5.5及以前 | 无法稳定支持Online DDL,结构变更需高强度锁保护,部分场景需拷贝整表 | 业务写入会中断,变更要低峰窗口 |
| MySQL 5.6 | Online DDL支持,ADD INDEX可使用ALGORITHM=INPLACE、LOCK=NONE | 执行阶段不阻塞读写,起止仍有短暂MDL锁 |
| MySQL 5.7 | 较5.6变化不大,锁机制延续并逐步完善 | 常见场景均可在线执行,但开始和提交阶段要注意 |
| MySQL 8.0 | 新增INSTANT算法,兼顾更多DDL场景加索引,仍以INPLACE为主 | 能力更强,但不代表所有操作都瞬间完成 |
所以,如果面试题只问“会锁表吗”,首答应该是一句话:MySQL 5.6之前,加索引可能锁表;5.6之后,在正常配置和语句条件下,加索引引起的阻塞被压缩到了一个非常小的窗口,并不会长时间锁表。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 拆开Online DDL:ALGORITHM和LOCK把锁细化到了哪个阶段
2.1 ALGORITHM=INPLACE不是完全不加锁,而是把锁集中在两个瞬间
很多人对“Online DDL不锁表”有个误解,以为整个执行过程业务完全无感。实际不是。
MySQL里执行一次ALTER TABLE,哪怕用了INPLACE,在操作最开始的准备阶段和最后提交阶段,都需要在表上获取一把MDL
