跳到主要内容
MySQL Online DDL 三大算法 INSTANT、INPLACE、COPY 差异详解 | 极客日志
SQL java 算法
MySQL Online DDL 三大算法 INSTANT、INPLACE、COPY 差异详解 综述由AI生成 详细解析了 MySQL Online DDL 的三种核心算法:INSTANT、INPLACE 和 COPY。INSTANT 仅修改元数据,速度最快且不阻塞;INPLACE 原地修改数据文件,轻度阻塞;COPY 创建新表复制数据,重度阻塞但兼容性好。文章对比了三者的实现原理、适用场景、锁机制及性能特征,并提供了生产环境中的最佳实践、故障处理策略及优化技巧,帮助开发者在面试及实际工作中选择合适的 DDL 方案。
花里胡哨 发布于 2026/3/30 更新于 2026/5/27 29 浏览一、三大算法核心对比概览
1.1 算法对比总览表
特性维度 INSTANT 算法 INPLACE 算法 COPY 算法 实现原理 仅修改元数据 原地修改数据文件 创建新表复制数据 阻塞级别 瞬间完成,基本不阻塞 轻度阻塞(短暂 MDL 锁) 重度阻塞(长 MDL 锁) 磁盘空间 几乎不占用额外空间 需要临时空间(索引重建) 需要双倍空间 执行速度 亚秒级 秒到分钟级 分钟到小时级 适用版本 MySQL 8.0.12+ MySQL 5.6+ 所有版本 回滚能力 支持(快速回滚) 支持(中间状态) 不支持
二、INSTANT 算法详解(最快速)
2.1 原理与实现机制
ALTER TABLE users ADD COLUMN last_login_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP , ALGORITHM= INSTANT;
核心原理 :
class InstantAlgorithm :
""" INSTANT 算法:仅修改数据字典(元数据),不修改实际数据文件 """
def execute (self, table, operation ):
""" 执行流程:
1. 获取 MDL 锁(极短暂)
2. 在表数据字典中添加新列的元数据
3. 更新数据字典中的列默认值
4. 释放 MDL 锁
"""
metadata_change_only = True
alter_metadata({
: table.name,
: ,
: {
: ,
: ,
: ,
:
}
})
'table_name'
'operation'
'ADD_COLUMN'
'column'
'name'
'last_login_time'
'type'
'TIMESTAMP'
'default'
'CURRENT_TIMESTAMP'
'position'
'LAST'
return
"Operation completed instantly"
2.2 支持的操作类型
ALTER TABLE t1 ADD COLUMN c INT , ALGORITHM= INSTANT;
ALTER TABLE t1 ADD COLUMN c INT AFTER b, ALGORITHM= INSTANT;
ALTER TABLE t1 DROP COLUMN c, ALGORITHM= INSTANT;
ALTER TABLE t1 RENAME COLUMN a TO b, ALGORITHM= INSTANT;
ALTER TABLE t1 ALTER COLUMN c SET DEFAULT 100 , ALGORITHM= INSTANT;
ALTER TABLE t1 ALTER COLUMN c DROP DEFAULT , ALGORITHM= INSTANT;
ALTER TABLE t1 ALTER INDEX idx_name INVISIBLE, ALGORITHM= INSTANT;
ALTER TABLE t1 ALTER INDEX idx_name VISIBLE, ALGORITHM= INSTANT;
ALTER TABLE t1 MODIFY COLUMN status ENUM('active' ,'inactive' ,'pending' ), ALGORITHM= INSTANT;
2.3 技术限制与内部实现 class InstantAlgorithmLimitations :
""" INSTANT 算法限制分析 """
def check_limitations (self, operation ):
limitations = {
'row_format_requirement' : '表必须是 DYNAMIC 或 COMPRESSED 格式' ,
'data_directory_requirement' : '不能有 DATA DIRECTORY 子句' ,
'temporary_table' : '不能是临时表' ,
'fulltext_index' : '不能有 FULLTEXT 索引' ,
'spatial_index' : '不能有 SPATIAL 索引' ,
'compressed_table' : '不能是 COMPRESSED 格式' ,
'encrypted_table' : '不能是加密表' ,
'max_instant_cols' : 64 ,
'partition_table' : '不支持分区表' ,
'virtual_columns' : '不支持虚拟列操作'
}
return limitations
def internal_implementation (self ):
""" 内部实现机制:
1. 在表结构末尾添加 instant 列位图
2. 新列数据存储在现有行的末尾
3. 对于已有数据,新列为 NULL 或默认值
4. 新插入数据包含新列值
"""
return {
'instant_bitmap' : '在表空间头存储哪些列是 instant 添加的' ,
'column_count' : '原始列数和 instant 列数分开存储' ,
'default_values' : '通过数据字典存储默认值' ,
'space_management' : '使用现有的未使用空间存储新列'
}
三、INPLACE 算法详解(最常用)
3.1 原理与执行过程
ALTER TABLE orders ADD INDEX idx_customer_id (customer_id), ALGORITHM= INPLACE, LOCK= NONE ;
class InplaceAlgorithm :
""" INPLACE 算法:原地修改数据文件,不需要创建新表 """
def execute (self, table, operation ):
""" 三阶段执行流程:
阶段 1: Prepare(准备阶段)
- 创建临时文件(.tmp)
- 准备需要的资源
- 获取共享 MDL 锁
阶段 2: Execute(执行阶段)
- 在原表空间内修改数据
- 重建索引(如需要)
- 更新数据字典
阶段 3: Commit(提交阶段)
- 提交修改
- 释放锁
- 清理临时文件
"""
phases = {
'phase1_prepare' : {
'duration' : '短暂' ,
'lock' : 'MDL_SHARED_UPGRADABLE' ,
'operations' : [
'验证操作可行性' ,
'分配临时空间' ,
'创建临时文件' ,
'初始化排序缓冲区'
]
},
'phase2_execute' : {
'duration' : '主要耗时阶段' ,
'lock' : 'MDL_EXCLUSIVE(短暂)' ,
'operations' : {
'add_index' : '读取数据 -> 排序 -> 构建 B+ 树' ,
'drop_index' : '标记索引为删除 -> 空间回收' ,
'optimize_table' : '碎片整理,页重组'
}
},
'phase3_commit' : {
'duration' : '短暂' ,
'lock' : 'MDL_EXCLUSIVE(极短)' ,
'operations' : [
'原子切换新结构' ,
'更新数据字典' ,
'清理临时文件' ,
'释放所有锁'
]
}
}
return phases
3.2 支持的操作类型
ALTER TABLE orders ADD INDEX idx_order_date (order_date), ALGORITHM= INPLACE;
ALTER TABLE orders DROP INDEX idx_order_date, ALGORITHM= INPLACE;
ALTER TABLE orders RENAME INDEX old_name TO new_name, ALGORITHM= INPLACE;
ALTER TABLE users MODIFY COLUMN age TINYINT UNSIGNED, ALGORITHM= INPLACE;
ALTER TABLE orders ADD CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id), ALGORITHM= INPLACE;
ALTER TABLE orders DROP FOREIGN KEY fk_user, ALGORITHM= INPLACE;
ALTER TABLE users ROW_FORMAT= DYNAMIC , ALGORITHM= INPLACE;
ALTER TABLE users CHARACTER SET utf8mb4, ALGORITHM= INPLACE;
ALTER TABLE locations ADD SPATIAL INDEX idx_point (point), ALGORITHM= INPLACE;
ALTER TABLE users FORCE, ALGORITHM= INPLACE;
3.3 INPLACE 算法变体:原地重建 class InplaceRebuildAlgorithm :
""" 原地重建算法:需要重建整个表,但仍在原表空间 """
def analyze_operations (self ):
return {
'requires_full_rebuild' : [
'修改列的数据类型(如 INT -> BIGINT)' ,
'修改字符集(需要重新编码)' ,
'修改 ROW_FORMAT' ,
'删除主键' ,
'添加/删除自增列' ,
'OPTIMIZE TABLE(碎片整理)'
],
'partial_rebuild' : [
'添加二级索引(仅重建索引)' ,
'删除二级索引(仅更新元数据)' ,
'修改索引类型' ,
'修改索引可见性'
],
'performance_characteristics' : {
'disk_space' : '需要额外空间存储中间数据' ,
'memory_usage' : '使用 sort buffer 排序' ,
'io_pattern' : '顺序读取,随机写入' ,
'parallelism' : 'MySQL 8.0 支持并行 DDL'
}
}
def execute_optimize_table (self ):
""" OPTIMIZE TABLE 的 INPLACE 实现
注意:实际上会创建临时表,但使用 INPLACE 算法
"""
steps = [
'1. 创建与原表结构相同的临时表' ,
'2. 逐行从原表读取数据,插入临时表(重建行)' ,
'3. 删除原表,重命名临时表' ,
'4. 重建索引'
]
return {
'actual_algorithm' : 'COPY 但标记为 INPLACE' ,
'reason' : '需要重建整个表来消除碎片' ,
'space_requirement' : '需要与原表相当的空间'
}
四、COPY 算法详解(最传统)
4.1 原理与执行过程
ALTER TABLE employees ADD COLUMN middle_name VARCHAR (50 ), ALGORITHM= COPY ;
class CopyAlgorithm :
""" COPY 算法:创建新表,复制数据,替换原表 """
def execute (self, table, operation ):
""" 五阶段执行流程:
阶段 1: 创建临时表
- 根据新结构创建临时表(#sql-xxx)
- 在新表上创建所有索引
阶段 2: 复制数据
- 逐行从原表读取数据
- 应用转换(如类型转换)
- 写入临时表
阶段 3: 同步数据
- 在复制期间应用 DML 操作
- 使用触发器捕获变更
阶段 4: 切换表
- 获取排他锁
- 重命名表:原表 -> 备份表,临时表 -> 原表
阶段 5: 清理
- 删除备份表
- 删除触发器
- 释放锁
"""
resource_requirements = {
'disk_space' : '原表大小 * 2(最坏情况)' ,
'memory' : '取决于 buffer pool 配置' ,
'io_operations' : '全表扫描 + 全表写入' ,
'lock_duration' : '整个复制过程持有排他锁' ,
'dml_blocking' : '完全阻塞读写'
}
return resource_requirements
4.2 COPY 算法的内部触发器机制
CREATE TRIGGER trg_employees_insert AFTER INSERT ON employees FOR EACH ROW BEGIN
INSERT INTO tmp_employees VALUES (NEW.* );
END ;
CREATE TRIGGER trg_employees_update AFTER UPDATE ON employees FOR EACH ROW BEGIN
UPDATE tmp_employees SET ... WHERE id = OLD.id;
END ;
CREATE TRIGGER trg_employees_delete AFTER DELETE ON employees FOR EACH ROW BEGIN
DELETE FROM tmp_employees WHERE id = OLD.id;
END ;
class CopyAlgorithmTriggers :
""" COPY 算法的触发器同步机制 """
def explain_sync_mechanism (self ):
return {
'trigger_creation' : {
'timing' : '数据复制开始前' ,
'types' : ['INSERT' , 'UPDATE' , 'DELETE' ],
'purpose' : '捕获 DDL 执行期间的 DML 变更'
},
'data_sync_flow' : {
'step1' : '用户执行 DML 操作' ,
'step2' : '触发器捕获变更' ,
'step3' : '应用到临时表' ,
'step4' : '继续复制剩余数据'
},
'performance_impact' : {
'dml_overhead' : '每个 DML 操作额外执行触发器逻辑' ,
'trigger_maintenance' : '需要维护触发器元数据' ,
'locking_issues' : '可能产生死锁'
}
}
五、三大算法对比深度分析
5.1 性能特征对比矩阵 class AlgorithmComparison :
""" 三大算法详细对比分析 """
def comparison_matrix (self ):
return {
'algorithm_comparison' : {
'INSTANT' : {
'blocking_level' : 'LOW(仅元数据锁)' ,
'disk_io' : '几乎为零' ,
'dml_impact' : '几乎无影响' ,
'disk_space' : '可忽略' ,
'recovery' : '秒级回滚' ,
'applicability' : '有限操作' ,
'version_requirement' : 'MySQL 8.0.12+'
},
'INPLACE' : {
'blocking_level' : 'MEDIUM(分阶段锁)' ,
'disk_io' : '中度(取决于数据量)' ,
'dml_impact' : '阶段 2 短暂阻塞' ,
'disk_space' : '需要临时空间' ,
'recovery' : '可中断,有中间状态' ,
'applicability' : '大部分 DDL 操作' ,
'version_requirement' : 'MySQL 5.6+'
},
'COPY' : {
'blocking_level' : 'HIGH(全程排他锁)' ,
'disk_io' : '重度(全表读写)' ,
'dml_impact' : '完全阻塞' ,
'disk_space' : '双倍空间' ,
'recovery' : '困难,需手动处理' ,
'applicability' : '所有 DDL 操作' ,
'version_requirement' : '所有版本'
}
},
'operation_support_matrix' : {
'ADD_COLUMN' : {
'INSTANT' : '✓(末尾或任意位置)' ,
'INPLACE' : '✓(需要重建表)' ,
'COPY' : '✓'
},
'DROP_COLUMN' : {
'INSTANT' : '✓(8.0.29+)' ,
'INPLACE' : '✓(需要重建表)' ,
'COPY' : '✓'
},
'ADD_INDEX' : {
'INSTANT' : '✗' ,
'INPLACE' : '✓' ,
'COPY' : '✓'
},
'DROP_INDEX' : {
'INSTANT' : '✗' ,
'INPLACE' : '✓' ,
'COPY' : '✓'
},
'MODIFY_COLUMN' : {
'INSTANT' : '✗' ,
'INPLACE' : '△(有限制)' ,
'COPY' : '✓'
},
'RENAME_TABLE' : {
'INSTANT' : '✗' ,
'INPLACE' : '✓' ,
'COPY' : '✓'
}
}
}
5.2 锁机制深度分析 class LockMechanismAnalysis :
""" 三大算法的锁机制分析 """
def analyze_lock_patterns (self ):
return {
'MDL_lock_types' : {
'MDL_SHARED' : '允许并发读,阻止写' ,
'MDL_SHARED_UPGRADABLE' : '允许并发读,准备升级' ,
'MDL_EXCLUSIVE' : '完全独占,阻止所有操作'
},
'algorithm_lock_usage' : {
'INSTANT' : {
'lock_type' : 'MDL_EXCLUSIVE(极短暂)' ,
'duration' : '亚秒级' ,
'concurrent_dml' : '几乎无阻塞' ,
'lock_contention' : '极低'
},
'INPLACE' : {
'phase1' : {
'lock' : 'MDL_SHARED_UPGRADABLE' ,
'duration' : '准备时间' ,
'dml' : '允许读写'
},
'phase2' : {
'lock' : 'MDL_EXCLUSIVE' ,
'duration' : '执行时间(主耗时)' ,
'dml' : '完全阻塞'
},
'phase3' : {
'lock' : 'MDL_EXCLUSIVE' ,
'duration' : '提交时间' ,
'dml' : '完全阻塞'
}
},
'COPY' : {
'lock_type' : 'MDL_EXCLUSIVE' ,
'duration' : '整个 DDL 过程' ,
'concurrent_dml' : '完全阻塞' ,
'lock_contention' : '高,容易导致超时'
}
},
'lock_timeout_issues' : {
'common_causes' : [
'长事务未提交' ,
'未提交的显式锁' ,
'备份操作进行中' ,
'复制延迟'
],
'solutions' : [
'使用 LOCK=NONE(如果支持)' ,
'分批执行 DDL' ,
'在低峰期执行' ,
'监控长事务'
]
}
}
六、生产环境最佳实践
6.1 算法选择决策树 class AlgorithmDecisionTree :
""" Online DDL 算法选择决策树 """
def decide_algorithm (self, operation, mysql_version, table_size ):
""" 决策逻辑:
1. 检查 MySQL 版本是否支持 INSTANT
2. 检查操作是否支持 INSTANT
3. 检查 INPLACE 是否支持
4. 默认使用 COPY
"""
decision_tree = {
'step1' : '检查 MySQL 版本 >= 8.0.12?' ,
'step2' : '检查操作是否支持 INSTANT?' ,
'step3' : '检查操作是否支持 INPLACE?' ,
'step4' : '使用 COPY 算法' ,
'instant_criteria' : {
'mysql_version' : '>= 8.0.12' ,
'table_format' : 'DYNAMIC 或 COMPRESSED' ,
'operation_type' : [
'ADD_COLUMN(任意位置)' ,
'DROP_COLUMN(8.0.29+)' ,
'RENAME_COLUMN' ,
'SET/DROP DEFAULT' ,
'索引可见性修改'
]
},
'inplace_criteria' : {
'mysql_version' : '>= 5.6' ,
'operation_type' : [
'ADD/DROP INDEX' ,
'ADD/DROP FOREIGN KEY' ,
'RENAME TABLE' ,
'修改表选项' ,
'OPTIMIZE TABLE'
],
'considerations' : [
'表大小影响执行时间' ,
'需要临时磁盘空间' ,
'阶段 2 会短暂阻塞'
]
},
'fallback_to_copy' : {
'scenarios' : [
'MySQL 版本 < 5.6' ,
'操作不支持 INPLACE' ,
'需要确保 100% 兼容性' ,
'小表,执行时间可接受'
],
'risks' : [
'完全阻塞读写' ,
'需要双倍磁盘空间' ,
'可能超时失败'
]
}
}
return decision_tree
6.2 安全执行 Online DDL
ALTER TABLE users ADD COLUMN last_ip VARCHAR (45 ), ALGORITHM= INPLACE, LOCK= NONE ;
SHOW WARNINGS;
EXPLAIN ALTER TABLE test_users ADD COLUMN last_ip VARCHAR (45 ), ALGORITHM= INPLACE, LOCK= NONE ;
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' , TIMED = 'YES'
WHERE NAME LIKE '%stage/innodb/alter%' ;
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 '%alter%' ;
ALTER TABLE big_table ADD COLUMN new_col INT DEFAULT 0 , ALGORITHM= INSTANT;
ALTER TABLE big_table ADD COLUMN new_col INT , ALGORITHM= COPY ;
UPDATE big_table SET new_col = 0 WHERE id BETWEEN 1 AND 1000000 ;
UPDATE big_table SET new_col = 0 WHERE id BETWEEN 1000001 AND 2000000 ;
6.3 故障处理与回滚 class DDLFailureRecovery :
""" Online DDL 故障处理策略 """
def handle_failure_scenarios (self ):
scenarios = {
'instant_algorithm_failure' : {
'cause' : '不满足 INSTANT 条件但指定了 ALGORITHM=INSTANT' ,
'symptoms' : '立即报错,无影响' ,
'recovery' : '重新执行合适的算法' ,
'sql' : "ALTER TABLE t1 ADD COLUMN c INT, ALGORITHM=INPLACE;"
},
'inplace_algorithm_failure' : {
'cause' : '磁盘空间不足、内存不足、锁超时' ,
'symptoms' : 'DDL 中断,表处于中间状态' ,
'recovery_steps' : [
'检查错误日志' ,
'查看 INFORMATION_SCHEMA.INNODB_TABLES' ,
'如果有临时表,手动清理' ,
'重启 MySQL(最后手段)'
],
'prevention' : [
'确保足够磁盘空间' ,
'设置合理的 lock_wait_timeout' ,
'监控长事务'
]
},
'copy_algorithm_failure' : {
'cause' : '磁盘空间不足、进程被 kill、服务器重启' ,
'symptoms' : '遗留#sql-xxx 临时表' ,
'recovery' : {
'case1' : '临时表存在,原表存在 → 手动清理临时表' ,
'case2' : '临时表存在,原表丢失 → 重命名临时表' ,
'case3' : '原表存在,临时表丢失 → 原表正常' ,
'case4' : '两者都损坏 → 从备份恢复'
},
'cleanup_sql' : [
"DROP TABLE IF EXISTS `#sql-xxx`;" ,
"RENAME TABLE `#sql-xxx` TO original_table;"
]
},
'lock_timeout_failure' : {
'cause' : 'MDL 锁等待超时' ,
'error' : 'ERROR 1205 (HY000): Lock wait timeout exceeded' ,
'solutions' : [
'增加 lock_wait_timeout' ,
'kill 阻塞的事务' ,
'在低峰期执行' ,
'使用 pt-online-schema-change'
],
'configuration' : [
"SET SESSION lock_wait_timeout = 86400;" ,
"SET GLOBAL innodb_lock_wait_timeout = 86400;"
]
}
}
return scenarios
七、高级优化技巧
7.1 MySQL 8.0 并行 DDL
SET SESSION innodb_ddl_threads = 4 ;
SET SESSION innodb_ddl_buffer_size = 1048576 ;
ALTER TABLE large_table ADD INDEX idx_column (column_name), ALGORITHM= INPLACE, LOCK= SHARED;
SELECT * FROM performance_schema.events_statements_current
WHERE SQL_TEXT LIKE '%ALTER TABLE%' ;
SHOW VARIABLES LIKE 'innodb_parallel%' ;
7.2 大表 DDL 优化策略 class LargeTableDDLOptimization :
""" 大表 Online DDL 优化策略 """
def optimization_strategies (self ):
return {
'strategy_1' : {
'name' : '分阶段执行' ,
'description' : '将一个大 DDL 拆分成多个小 DDL' ,
'example' : [
'1. 添加允许 NULL 的列(INSTANT)' ,
'2. 分批更新默认值(避免长事务)' ,
'3. 修改列为 NOT NULL(INPLACE)'
],
'benefits' : '减少单次锁持有时间'
},
'strategy_2' : {
'name' : '利用从库先行' ,
'description' : '先在从库执行,验证后再在主库执行' ,
'steps' : [
'1. 在从库执行 DDL' ,
'2. 监控复制延迟' ,
'3. 验证业务影响' ,
'4. 主库低峰期执行'
],
'tools' : 'pt-online-schema-change, gh-ost'
},
'strategy_3' : {
'name' : '智能算法选择' ,
'description' : '根据表大小和操作类型选择最优算法' ,
'decision_matrix' : {
'small_table(<10GB)' : '根据操作选择' ,
'medium_table(10-100GB)' : '优先 INPLACE' ,
'large_table(>100GB)' : '使用外部工具'
},
'external_tools' : [
'pt-online-schema-change' ,
'gh-ost' ,
'Facebook 的 OSC'
]
},
'strategy_4' : {
'name' : '资源优化配置' ,
'description' : '调整 MySQL 参数优化 DDL 性能' ,
'parameters' : {
'innodb_buffer_pool_size' : '增大缓冲池' ,
'innodb_sort_buffer_size' : '增大排序缓冲区' ,
'innodb_online_alter_log_max_size' : '增大在线日志' ,
'tmp_table_size' : '增大临时表大小'
},
'recommendations' : [
'DDL 前预热缓冲池' ,
'关闭不必要的监控' ,
'确保足够磁盘 IOPS'
]
}
}
def pt_online_schema_change_example (self ):
""" 使用 pt-online-schema-change 的示例 """
return {
'command' : '''pt-online-schema-change \\\n--alter="ADD COLUMN last_login TIMESTAMP" \\\nD=database,t=users \\\n--execute \\\n--max-load="Threads_running=25" \\\n--critical-load="Threads_running=50" \\\n--chunk-size=1000 \\\n--max-lag=1''' ,
'working_principle' : {
'step1' : '创建影子表(新结构)' ,
'step2' : '在原表上创建触发器' ,
'step3' : '分批复制数据' ,
'step4' : '原子切换表' ,
'step5' : '清理旧表'
},
'advantages' : [
'真正的在线,几乎不阻塞' ,
'可暂停和恢复' ,
'详细的进度报告' ,
'自动负载监控'
],
'disadvantages' : [
'需要额外磁盘空间' ,
'触发器性能开销' ,
'外键处理复杂' ,
'需要足够的权限'
]
}
八、面试要点总结
8.1 核心概念记忆点
INSTANT 算法:元数据级别修改,亚秒级完成,MySQL 8.0+
INPLACE 算法:原地修改,分阶段锁,支持大部分 DDL
COPY 算法:创建新表复制数据,完全阻塞,兼容性好
阻塞程度:INSTANT < INPLACE < COPY
执行速度:INSTANT > INPLACE > COPY
磁盘使用:INSTANT < INPLACE < COPY
8.2 常见面试问题 Q1:什么情况下 INPLACE 算法实际上需要复制整个表?
答:INPLACE 算法在以下情况需要重建整个表:
修改列的数据类型(如 VARCHAR(10) → VARCHAR(20))
修改字符集(需要重新编码数据)
修改表的 ROW_FORMAT
删除主键
添加/删除自增列
某些分区表操作
虽然标记为 INPLACE,但实际上需要复制数据,只是不需要创建新表文件。
查看官方文档的 Online DDL 支持矩阵
使用 EXPLAIN 分析:EXPLAIN ALTER TABLE ...
查看 SHOW WARNINGS 输出
查询 INFORMATION_SCHEMA.INNODB_SYS_TABLES
测试环境实际执行观察
MySQL 8.0 开始,如果不指定 ALGORITHM,会按 INSTANT→INPLACE→COPY 顺序自动选择。
空间限制:需要足够的磁盘空间(尤其是 COPY 算法)
性能影响:INPLACE 的阶段 2 会短暂阻塞
复制延迟:在复制环境中可能导致延迟
外键约束:某些操作不支持有外键的表
触发器影响:COPY 算法使用触发器可能影响性能
元数据锁:可能与其他事务冲突
最佳实践:先在从库测试,使用监控工具,准备回滚方案。
Q4:MySQL 8.0 在 Online DDL 方面有哪些重要改进?
INSTANT 算法:支持添加列等操作(8.0.12+)
原子 DDL:DDL 操作要么完全成功,要么完全回滚
并行 DDL:支持并行创建索引(8.0.14+)
更好的进度监控:通过 performance_schema
DDL 日志:避免 DDL 执行中的数据丢失
更多的 INPLACE 操作:扩大了支持范围
这些改进大大提高了 DDL 的可靠性和性能。
这个完整的 Online DDL 三大算法解析,从基础原理到生产实践,涵盖了面试和工作中的各种场景,帮助你深入理解 MySQL 的 DDL 机制。
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online