MySQL如何实现在不停止服务的情况下修改表结构_利用Online DDL

胖墨君_6813

胖墨君_6813

2026-04-11

875人浏览

原创

mysql 5.6前alter table默认锁表因全表拷贝+mdl_write锁;5.6起支持online ddl,但仅部分操作(如加删二级索引、改默认值)可lock=none,需显式指定algorithm和lock并验证。

mysql如何实现在不停止服务的情况下修改表结构_利用online ddl

ALTER TABLE 为什么默认会锁表

MySQL 5.6 之前,ALTER TABLE 几乎总是触发全表拷贝(copy-alter),期间对原表加 MDL_WRITE 锁,所有 DML(INSERT/UPDATE/DELETE)都会被阻塞。哪怕只是加个 VARCHAR(255) 字段,也可能卡住业务几小时。

根本原因是老版本没有分离“元数据变更”和“数据重组织”的能力——结构改了,数据就得重排、重建索引、重写磁盘文件。

5.6 起引入 Online DDL,但不是所有操作都在线;是否真正不锁表,取决于具体操作类型、存储引擎(仅 InnoDB 支持完整 Online DDL)、以及是否显式指定算法和锁级别。

哪些 ALTER 操作能真正 Online(InnoDB)

不是所有 ALTER TABLE 都能免锁。以下常见操作在 MySQL 5.6+ 中可做到 ALGORITHM=INPLACE 且 LOCK=NONE(即读写都不阻塞):

  • 添加/删除二级索引(ADD INDEX / DROP INDEX)
  • 修改列默认值(ALTER COLUMN ... SET DEFAULT)
  • 重命名列(CHANGE COLUMN 或 RENAME COLUMN,但不能改类型或约束)
  • 添加虚拟列(ADD VIRTUAL COLUMN)
  • 修改自增值(ALTER TABLE ... AUTO_INCREMENT = N)

而这些操作即使指定 ALGORITHM=INPLACE,仍至少需要 LOCK=SHARED(阻塞写,允许读):

  • 修改列类型(如 VARCHAR(50) → VARCHAR(100) 在部分场景下可,但 INT → BIGINT 不行)
  • 添加 NOT NULL 列(无默认值时必须全表扫描补 NULL,会锁写)
  • 修改主键(DROP PRIMARY KEY + ADD PRIMARY KEY 组合通常触发拷贝)

如何强制控制 Online DDL 行为

MySQL 允许显式指定 ALGORITHM 和 LOCK 提示,让执行更可控。不写的话,MySQL 自动选最优策略,但有时它会“保守选择”导致锁表。

推荐始终显式声明,例如:

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载
ALTER TABLE users ADD COLUMN status TINYINT DEFAULT 0, ALGORITHM=INPLACE, LOCK=NONE;

关键参数含义:

  • ALGORITHM=INPLACE:禁止拷贝表,只做原地修改(失败则报错,不降级)
  • ALGORITHM=COPY:强制全表拷贝(等价于旧版行为)
  • LOCK=NONE:不锁读写(仅部分操作支持)
  • LOCK=SHARED:允许读,阻塞写
  • LOCK=DEFAULT:让 MySQL 自行决定最小锁级别(默认值,但不可靠)

注意:ALGORITHM=INPLACE 并不保证 LOCK=NONE;必须两者配合检查。执行前可用 EXPLAIN FORMAT=JSON 查看预估行为(MySQL 8.0.12+ 支持):

EXPLAIN FORMAT=JSON ALTER TABLE users ADD INDEX idx_email (email);

返回 JSON 中的 alter_algorithm 和 lock_level 字段就是真实决策依据。

线上执行前必须验证的三件事

Online DDL 不是银弹,尤其在大表上,容易因磁盘 IO、内存不足、长事务或复制延迟引发问题。

  • 确认没有活跃的长事务:SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(NOW() - trx_started) > 60; —— 长事务会阻止 DDL 获取元数据锁,导致 DDL 排队甚至超时
  • 检查磁盘空间:ALGORITHM=INPLACE 仍需临时排序空间(尤其建索引),建议预留 ≥ 表大小 20% 的 tmpdir 空间
  • 观察从库延迟:SHOW SLAVE STATUS\G 中的 Seconds_Behind_Master —— Online DDL 在主库秒级完成,但从库可能因单线程回放变慢,造成复制积压

最稳妥的做法:先在从库执行,确认无异常、无延迟飙升,再上主库;或者用 pt-online-schema-change(Percona Toolkit)兜底,它用触发器模拟 Online DDL,兼容性更强,但有额外性能开销和风险点(比如触发器失效、binlog 格式限制)。

真正麻烦的从来不是语法对不对,而是你没看到的那个未提交事务,或者那个正在跑的报表查询。

相关文章

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

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

下载

相关标签:

mysql

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

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4203

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

891

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1089

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

6101

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

2963

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

6080

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

8181

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1110

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

972

5

热门下载

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

精品课程

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

共1课时 | 183人学习