mysql 5.6+加索引绝大多数情况下不锁表,但需显式指定algorithm=inplace和lock=none才能真正支持并发读写;默认lock=default可能退化为共享或排他锁,添加二级索引支持lock=none,而修改列类型、增删主键等仍需copy算法必然锁表。

MySQL 5.6+ 加索引到底锁不锁表
绝大多数情况下不锁表,但“不锁”是相对的——ALGORITHM=INPLACE + LOCK=NONE 才真正支持并发读写;默认 LOCK=DEFAULT 可能退化为共享锁甚至排他锁,尤其在大表或低版本上容易误判。
关键不是“能不能加”,而是“加的时候别人还能不能改”。MySQL 5.6 起引入 Online DDL,但仅对特定操作生效:添加/删除二级索引、重命名索引等支持 LOCK=NONE;而修改列类型、增删主键、加全文索引仍需拷贝表(ALGORITHM=COPY),必然锁表。
-
SHOW VARIABLES LIKE 'innodb_file_per_table'必须为ON,否则无法使用INPLACE算法 - 执行前用
EXPLAIN FORMAT=JSON查看 DDL 计划,确认"alter_algorithm": "inplace"和"lock": "none" - 若提示
"lock": "shared",说明写操作会被阻塞,需避开业务高峰
怎么强制走 Online DDL 不锁表
靠 MySQL 自动判断(LOCK=DEFAULT)风险高,尤其当表有外键、触发器或存在长事务时,它可能悄悄降级为 ALGORITHM=COPY。必须显式指定参数控制行为。
加二级索引的标准安全写法:
ALTER TABLE users ADD INDEX idx_email (email) ALGORITHM=INPLACE, LOCK=NONE;
如果报错 ALGORITHM=INPLACE is not supported,说明操作不兼容,得换方案;若报错 LOCK=NONE is not supported,说明当前操作允许并发但需短暂锁元数据(LOCK=SHARED 是底线)。
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
- 不要省略
ALGORITHM=INPLACE—— 默认可能 fallback 到 COPY -
LOCK=NONE失败时,优先尝试LOCK=SHARED(读可用,写暂停),比直接锁表好 - 避免在从库上直接执行,GTID 或并行复制下可能引发延迟突增
大表加索引时并发量怎么控
即使 LOCK=NONE,加索引本身是 I/O 和 CPU 密集型操作,会显著拖慢查询响应,特别是当 buffer pool 压力大、磁盘吞吐不足时,SELECT 可能变慢,INSERT/UPDATE 的延迟也会升高——这不是锁,是资源争抢。
真实影响来自三方面:聚簇索引扫描开销、排序构建索引项、刷脏页压力。所以得从外部限流:
- 用
pt-online-schema-change(Percona Toolkit)分批处理,每批只改几百行,自动控制--max-load和--critical-load - 若用原生命令,配合
SET innodb_buffer_pool_size临时调小(避免占满),加完再调回 - 监控
SHOW ENGINE INNODB STATUS\G中的FILE I/O和LOG部分,发现pending normal aio reads持续 > 10 就说明磁盘已成瓶颈
为什么有时候明明写了 LOCK=NONE 还被卡住
常见原因不是语法错,而是隐式条件冲突:比如表上有未提交事务、正在运行的 SELECT ... FOR UPDATE、或者其它 DDL 正在排队。MySQL 在开始阶段要获取元数据锁(MDL),只要有一个活跃的 MDL 冲突,整个 DDL 就会挂起等待。
典型表现是 SHOW PROCESSLIST 里状态为 Waiting for table metadata lock,且持续几十秒以上。
- 先查
SELECT * FROM information_schema.INNODB_TRX WHERE trx_state = 'RUNNING',找长时间未提交的事务 - 再查
SELECT * FROM information_schema.PROCESSLIST WHERE COMMAND != 'Sleep' AND TIME > 60,杀掉慢连接 - 注意:
KILL一个事务后,InnoDB 回滚可能很慢(尤其大事务),此时加索引仍会等回滚完成
最易被忽略的一点:DDL 操作本身也参与 MDL 排队。如果前面有个大事务没结束,后面所有 DDL 都得等——不是锁表,是“等锁”。










