MySQL加索引会导致数据库锁表吗

 更新时间:2026年01月04日 10:27:31   作者:萧曵 丶  
本文详细介绍了MySQL在线DDL操作的机制,包括不同版本的影响、索引类型和操作方式对锁表的影响,以及如何查看和监控DDL操作的锁机制,通过实际案例和最佳实践,提供了在生产环境中高效执行DDL操作的建议,感兴趣的朋友跟随小编一起看看吧

答案是:可能会锁表,但取决于MySQL版本、索引类型和操作方式。

1. MySQL不同版本的区别

MySQL 5.6及之前版本

会锁表(多数情况下)

  • 创建索引时会对表加上排他锁(X锁)
  • 期间表不可读写,直到索引创建完成
  • 对生产环境影响较大

MySQL 5.6及之后版本(Online DDL)

通常不锁表,但仍有短暂锁定

  • 支持Online DDL(在线数据定义语言)
  • 创建二级索引时,允许DML操作(INSERT、UPDATE、DELETE)
  • 但开始和结束时有短暂元数据锁

2. 不同索引创建方式的锁表情况

创建普通二级索引(最常见场景)

-- MySQL 5.6+ 通常不锁表
CREATE INDEX idx_name ON users(name);

锁表情况:

  • 开始阶段:获取元数据锁(MDL),非常短暂(毫秒级)
  • 创建阶段:允许DML操作,不阻塞读写
  • 结束阶段:再次获取元数据锁,更新表定义

创建主键索引或改变主键

-- 可能锁表,尤其是表已经有数据时
ALTER TABLE users ADD PRIMARY KEY (id);

创建全文索引或空间索引

-- 通常需要锁表
CREATE FULLTEXT INDEX idx_content ON articles(content);

3. Online DDL的具体行为

支持的Online DDL操作(通常不锁表)

-- 1. 添加二级索引
ALTER TABLE users ADD INDEX idx_email(email);
-- 2. 删除索引
ALTER TABLE users DROP INDEX idx_email;
-- 3. 重命名索引
ALTER TABLE users RENAME INDEX old_name TO new_name;
-- 4. 修改索引类型(如改为HASH)
ALTER TABLE users DROP INDEX idx_email, ADD INDEX idx_email USING HASH(email);

可能需要锁表的操作

-- 1. 修改主键
ALTER TABLE users DROP PRIMARY KEY, ADD PRIMARY KEY(new_id);
-- 2. 修改列数据类型
ALTER TABLE users MODIFY COLUMN name VARCHAR(100);
-- 3. 添加自增列
ALTER TABLE users ADD COLUMN id INT AUTO_INCREMENT PRIMARY KEY;
-- 4. 添加/删除外键约束
ALTER TABLE orders ADD FOREIGN KEY (user_id) REFERENCES users(id);

4. 查看DDL操作的锁机制

查看DDL操作是否支持Online

-- 查看支持的算法和锁类型
SHOW CREATE TABLE users\G
-- 查看具体的DDL操作信息
SELECT * FROM information_schema.INNODB_TRX 
WHERE trx_state = 'LOCK WAIT';
-- 或者使用performance_schema监控
SELECT * FROM performance_schema.metadata_locks;

使用INPLACE和COPY算法对比

-- 使用INPLACE算法(尽量减少锁表)
ALTER TABLE users ADD INDEX idx_phone(phone) ALGORITHM=INPLACE;
-- 使用COPY算法(会锁表)
ALTER TABLE users ADD INDEX idx_phone(phone) ALGORITHM=COPY;

5. 实际案例和最佳实践

案例1:安全添加索引(推荐)

-- 1. 首先在测试环境验证
-- 2. 选择业务低峰期执行
-- 3. 监控进程状态
-- 使用INPLACE算法,指定不锁表
ALTER TABLE large_table 
ADD INDEX idx_create_time(create_time),
ALGORITHM=INPLACE,
LOCK=NONE;

案例2:大表添加索引的优化

-- 对于超大表,可以采用pt-online-schema-change工具
-- 而不是直接执行ALTER TABLE
-- 使用pt-online-schema-change(Percona Toolkit)
pt-online-schema-change \
  --alter "ADD INDEX idx_email(email)" \
  D=database,t=users \
  --execute

案例3:监控DDL执行进度

-- 在MySQL 5.7+中可以监控进度
SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED,
       (WORK_COMPLETED/WORK_ESTIMATED)*100 as progress_pct
FROM performance_schema.events_stages_current
WHERE EVENT_NAME LIKE '%stage/innodb/alter%';

6. 不同锁级别的影响

-- LOCK=NONE: 允许读写,不阻塞任何操作
ALTER TABLE users ADD INDEX idx_name(name) LOCK=NONE;
-- LOCK=SHARED: 允许读,阻塞写
ALTER TABLE users ADD INDEX idx_name(name) LOCK=SHARED;
-- LOCK=EXCLUSIVE: 阻塞读写(全表锁)
ALTER TABLE users ADD INDEX idx_name(name) LOCK=EXCLUSIVE;

7. 生产环境最佳实践

1.评估影响

-- 先检查表大小和当前负载
SELECT 
  TABLE_NAME,
  ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS 'Size(MB)',
  TABLE_ROWS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_db'
AND TABLE_NAME = 'your_table';

2.使用合适的工具

  • 小表:直接使用ALTER TABLE ... ALGORITHM=INPLACE
  • 大表:使用pt-online-schema-changegh-ost
  • 云数据库:使用云服务商提供的在线DDL功能

3.执行步骤

# 1. 备份表结构
mysqldump -d your_db your_table > table_structure.sql
# 2. 测试环境验证
# 3. 业务低峰期执行
# 4. 监控性能影响
# 5. 验证索引效果

4.避免的陷阱

-- 错误做法:在事务中执行DDL
START TRANSACTION;
-- 其他DML操作...
ALTER TABLE users ADD INDEX idx_name(name); -- 可能导致长时间锁表
COMMIT;
-- 正确做法:单独执行DDL
ALTER TABLE users ADD INDEX idx_name(name);

8. 常见问题解答

Q: Online DDL真的完全不锁表吗?

A: 不完全。Online DDL在开始和结束时需要获取元数据锁,虽然非常短暂(毫秒到秒级),但如果有长时间未提交的事务,可能会导致等待。

Q: 如何知道DDL操作是否在执行中?

-- 查看当前运行进程
SHOW PROCESSLIST;
-- 或者使用sys库(MySQL 5.7+)
SELECT * FROM sys.session WHERE command = 'Query';

Q: 添加索引失败会怎样?

A: MySQL会回滚操作,表会恢复到之前状态,但期间可能消耗了大量系统资源。

9. 总结

场景是否锁表建议
MySQL 5.6+,添加二级索引基本不锁表使用ALGORITHM=INPLACE, LOCK=NONE
修改主键或列类型通常锁表使用pt-online-schema-change
大表添加索引可能长时间锁表使用gh-ost或分批操作
生产环境高峰期尽量不操作选择业务低峰期

最终建议:

  • MySQL 5.6+版本:添加普通二级索引通常不锁表,可放心使用
  • 主键操作或列修改:需要谨慎,可能锁表
  • 超大表操作:使用专业工具(pt-online-schema-change、gh-ost)
  • 生产环境:先在测试环境验证,选择合适时间执行
  • 监控:执行时监控数据库性能和锁状态

        在大多数现代MySQL部署中(5.6+),正确使用Online DDL可以实现在不锁表的情况下添加索引,对业务影响极小。

到此这篇关于MySQL加索引会导致数据库锁表吗的文章就介绍到这了,更多相关mysql加索引会不会导致锁表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL学习之事务详解

    MySQL学习之事务详解

    在数据库中 事务(transaction) 可以把多个SQL给打包到一起, 即将多个SQL语句变成一个整体, 也就是说一个事务中的所有操作要么全部成功执行, 要么完全不执行.本文主要来和大家聊聊事务的使用,需要的可以参考一下
    2022-12-12
  • Centos7下MySQL安装教程

    Centos7下MySQL安装教程

    这篇文章主要为大家详细介绍了Centos7下MySQL安装教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • MySQL 中的 JSON_CONTAIN用法示例详解

    MySQL 中的 JSON_CONTAIN用法示例详解

    JSON_CONTAINS 函数用于检查一个JSON文档中是否包含另一个 JSON 文档,这篇文章给大家介绍JSON_CONTAINS 的用法、语法、示例及其应用场景,感兴趣的朋友跟随小编一起看看吧
    2025-11-11
  • MySQL在Linux系统中隐藏命令行中的密码的方法

    MySQL在Linux系统中隐藏命令行中的密码的方法

    这篇文章主要介绍了MySQL在Linux系统中隐藏命令行中的密码的方法,作者利用简单的C程序实现,需要的朋友可以参考下
    2015-06-06
  • mysql中Table is read only的解决方法小结

    mysql中Table is read only的解决方法小结

    本文章总结了关于在linux与windows中 mysql出现Table is read only解决办法总结,有需要的朋友可参考一下
    2013-01-01
  • MySQL误删数据或者丢失?这6种方案能帮你快速恢复!

    MySQL误删数据或者丢失?这6种方案能帮你快速恢复!

    MySQL误删数据了?这6种方案能帮你快速恢复!,有位小伙伴不小心把测试环境MySQL表中所有数据都误删了,问我要如何快速恢复?幸好他误删的是测试环境,非生产环境,我遇到过有同事把生产环境会员表中的数据误删除的情况,这篇文章跟大家一起聊聊MySQL如何快速恢复误删数据
    2025-09-09
  • 深入理解mysql SET NAMES和mysql(i)_set_charset的区别

    深入理解mysql SET NAMES和mysql(i)_set_charset的区别

    最近公司组织了个PHP安全编程的培训, 其中涉及到一部分关于Mysql的 SET NAMES 和mysql_set_charset (mysqli_set_charset)的内容
    2012-01-01
  • phpstudy安装后mysql无法启动的解决

    phpstudy安装后mysql无法启动的解决

    本文主要介绍了phpstudy安装后mysql无法启动的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • MySQL安装starting the server失败的2种解决办法(推荐!)

    MySQL安装starting the server失败的2种解决办法(推荐!)

    MySQL是一个非常强大的关系型数据库,但有些初学者在安装配置的时候,遇到种种的困难,下面这篇文章主要给大家介绍了关于MySQL安装starting the server失败的2种解决办法,需要的朋友可以参考下
    2023-04-04
  • 快速修复损坏的MySQL数据库

    快速修复损坏的MySQL数据库

    在长时间使用 MySQL 后,数据库可能会出现一些问题。大多数问题可以通过简单的操作进行快速修复。下面介绍两种快速检修 MySQL 数据库的方法。
    2011-06-06

最新评论