一、三大算法核心对比概览
1.1 算法对比总览表
| 特性维度 | INSTANT算法 | INPLACE算法 | COPY算法 |
|---|---|---|---|
| 实现原理 | 仅修改元数据 | 原地修改数据文件 | 创建新表复制数据 |
| 阻塞级别 | 瞬间完成,基本不阻塞 | 轻度阻塞(短暂MDL锁) | 重度阻塞(长MDL锁) |
| 磁盘空间 | 几乎不占用额外空间 | 需要临时空间(索引重建) | 需要双倍空间 |
| 执行速度 | 亚秒级 | 秒到分钟级 | 分钟到小时级 |
| 适用版本 | MySQL 8.0.12+ | MySQL 5.6+ | 所有版本 |
| 回滚能力 | 支持(快速回滚) | 支持(中间状态) | 不支持 |
二、INSTANT算法详解(最快速)
2.1 原理与实现机制
sql
复制
下载
-- INSTANT算法执行示例
ALTER TABLE users ADD COLUMN last_login_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, ALGORITHM=INSTANT;
核心原理:
python
复制
下载
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' # MySQL 8.0支持任意位置添加
}
})
# 表数据文件(.ibd)完全不修改
return "Operation completed instantly"
2.2 支持的操作类型
sql
复制
下载
-- MySQL 8.0支持的INSTANT操作
-- 1. 添加列(默认到最后,8.0.12+支持任意位置)
ALTER TABLE t1 ADD COLUMN c INT, ALGORITHM=INSTANT;
ALTER TABLE t1 ADD COLUMN c INT AFTER b, ALGORITHM=INSTANT;
-- 2. 删除列(8.0.29+)
ALTER TABLE t1 DROP COLUMN c, ALGORITHM=INSTANT;
-- 3. 重命名列(8.0.28+)
ALTER TABLE t1 RENAME COLUMN a TO b, ALGORITHM=INSTANT;
-- 4. 设置/删除默认值
ALTER TABLE t1 ALTER COLUMN c SET DEFAULT 100, ALGORITHM=INSTANT;
ALTER TABLE t1 ALTER COLUMN c DROP DEFAULT, ALGORITHM=INSTANT;
-- 5. 修改索引可见性(8.0.23+)
ALTER TABLE t1 ALTER INDEX idx_name INVISIBLE, ALGORITHM=INSTANT;
ALTER TABLE t1 ALTER INDEX idx_name VISIBLE, ALGORITHM=INSTANT;
-- 6. 修改ENUM/SET值添加(末尾添加)
ALTER TABLE t1 MODIFY COLUMN status ENUM('active','inactive','pending'), ALGORITHM=INSTANT;
2.3 技术限制与内部实现
python
复制
下载
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, # MySQL 8.0.29后移除限制
'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 原理与执行过程
sql
复制
下载
-- INPLACE算法执行示例
ALTER TABLE orders ADD INDEX idx_customer_id (customer_id), ALGORITHM=INPLACE, LOCK=NONE;
核心原理:
python
复制
下载
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
篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc
需要全套面试笔记及答案
【点击此处即可/免费获取】
3.2 支持的操作类型
sql
复制
下载
-- INPLACE支持的主要操作
-- 1. 索引操作(最常用)
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;
-- 2. 修改列类型(有限制)
ALTER TABLE users MODIFY COLUMN age TINYINT UNSIGNED, ALGORITHM=INPLACE;
-- 3. 添加/删除外键(8.0+)
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;
-- 4. 修改表选项
ALTER TABLE users ROW_FORMAT=DYNAMIC, ALGORITHM=INPLACE;
ALTER TABLE users CHARACTER SET utf8mb4, ALGORITHM=INPLACE;
-- 5. 空间列操作
ALTER TABLE locations ADD SPATIAL INDEX idx_point (point), ALGORITHM=INPLACE;
-- 6. 重建表(相当于OPTIMIZE TABLE)
ALTER TABLE users FORCE, ALGORITHM=INPLACE;
3.3 INPLACE算法变体:原地重建
python
复制
下载
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 原理与执行过程
sql
复制
下载
-- COPY算法执行示例
ALTER TABLE employees ADD COLUMN middle_name VARCHAR(50), ALGORITHM=COPY;
核心原理:
python
复制
下载
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算法的内部触发器机制
sql
复制
下载
-- COPY算法使用的触发器(MySQL内部自动创建)
-- 1. 复制开始前创建触发器
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;
python
复制
下载
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 性能特征对比矩阵
python
复制
下载
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 锁机制深度分析
sql
复制
下载
-- 锁机制对比示例
-- INSTANT算法:极短暂的MDL锁
LOCK TABLES users WRITE; -- 用户手动锁,INSTANT不需要
-- INPLACE算法:阶段性的MDL锁
-- 阶段1: MDL_SHARED_UPGRADABLE(允许读)
-- 阶段2: MDL_EXCLUSIVE(短暂,阻塞所有操作)
-- 阶段3: MDL_EXCLUSIVE(极短,提交变更)
-- COPY算法:长时间的MDL_EXCLUSIVE锁
-- 整个DDL过程都持有排他锁
python
复制
下载
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 算法选择决策树
python
复制
下载
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
篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc
需要全套面试笔记及答案
【点击此处即可/免费获取】
6.2 安全执行Online DDL
sql
复制
下载
-- 1. 预检查:查看DDL执行计划
ALTER TABLE users
ADD COLUMN last_ip VARCHAR(45),
ALGORITHM=INPLACE,
LOCK=NONE;
-- 查看实际执行计划
SHOW WARNINGS;
-- 2. 测试环境验证
-- 在测试环境执行相同DDL,观察影响
EXPLAIN ALTER TABLE test_users
ADD COLUMN last_ip VARCHAR(45),
ALGORITHM=INPLACE,
LOCK=NONE;
-- 3. 监控执行进度(MySQL 8.0+)
-- 开启performance_schema
UPDATE performance_schema.setup_instruments
SET ENABLED = 'YES', TIMED = 'YES'
WHERE NAME LIKE '%stage/innodb/alter%';
-- 查看DDL进度
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%';
-- 4. 分批执行大表DDL
-- 方法1:使用pt-online-schema-change
-- 方法2:手动分批(添加列示例)
ALTER TABLE big_table
ADD COLUMN new_col INT DEFAULT 0,
ALGORITHM=INSTANT; -- 8.0支持
-- 如果是5.7,使用COPY但分批次更新
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 故障处理与回滚
python
复制
下载
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
sql
复制
下载
-- MySQL 8.0.14+ 支持并行创建索引
SET SESSION innodb_ddl_threads = 4; -- 设置并行线程数
SET SESSION innodb_ddl_buffer_size = 1048576; -- 设置DDL缓冲区
ALTER TABLE large_table
ADD INDEX idx_column (column_name),
ALGORITHM=INPLACE,
LOCK=SHARED;
-- 查看并行DDL状态
SELECT * FROM performance_schema.events_statements_current
WHERE SQL_TEXT LIKE '%ALTER TABLE%';
-- 配置并行DDL参数
SHOW VARIABLES LIKE 'innodb_parallel%';
/*
innodb_parallel_read_threads = 4
innodb_ddl_threads = 4
innodb_ddl_buffer_size = 1048576
*/
7.2 大表DDL优化策略
python
复制
下载
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 \\
--alter="ADD COLUMN last_login TIMESTAMP" \\
D=database,t=users \\
--execute \\
--max-load="Threads_running=25" \\
--critical-load="Threads_running=50" \\
--chunk-size=1000 \\
--max-lag=1
""",
'working_principle': {
'step1': '创建影子表(新结构)',
'step2': '在原表上创建触发器',
'step3': '分批复制数据',
'step4': '原子切换表',
'step5': '清理旧表'
},
'advantages': [
'真正的在线,几乎不阻塞',
'可暂停和恢复',
'详细的进度报告',
'自动负载监控'
],
'disadvantages': [
'需要额外磁盘空间',
'触发器性能开销',
'外键处理复杂',
'需要足够的权限'
]
}
八、面试要点总结
8.1 核心概念记忆点
text
复制
下载
1. INSTANT算法:元数据级别修改,亚秒级完成,MySQL 8.0+
2. INPLACE算法:原地修改,分阶段锁,支持大部分DDL
3. COPY算法:创建新表复制数据,完全阻塞,兼容性好
关键区别:
- 阻塞程度:INSTANT < INPLACE < COPY
- 执行速度:INSTANT > INPLACE > COPY
- 磁盘使用:INSTANT < INPLACE < COPY
8.2 常见面试问题
Q1:什么情况下INPLACE算法实际上需要复制整个表?
text
复制
下载
答:INPLACE算法在以下情况需要重建整个表:
1. 修改列的数据类型(如VARCHAR(10) → VARCHAR(20))
2. 修改字符集(需要重新编码数据)
3. 修改表的ROW_FORMAT
4. 删除主键
5. 添加/删除自增列
6. 某些分区表操作
虽然标记为INPLACE,但实际上需要复制数据,只是不需要创建新表文件。
Q2:如何判断一个DDL操作使用哪种算法?
text
复制
下载
答:可以通过以下方式:
1. 查看官方文档的Online DDL支持矩阵
2. 使用EXPLAIN分析:EXPLAIN ALTER TABLE ...
3. 查看SHOW WARNINGS输出
4. 查询INFORMATION_SCHEMA.INNODB_SYS_TABLES
5. 测试环境实际执行观察
MySQL 8.0开始,如果不指定ALGORITHM,会按INSTANT→INPLACE→COPY顺序自动选择。
Q3:Online DDL有哪些限制和风险?
text
复制
下载
答:主要限制和风险包括:
1. 空间限制:需要足够的磁盘空间(尤其是COPY算法)
2. 性能影响:INPLACE的阶段2会短暂阻塞
3. 复制延迟:在复制环境中可能导致延迟
4. 外键约束:某些操作不支持有外键的表
5. 触发器影响:COPY算法使用触发器可能影响性能
6. 元数据锁:可能与其他事务冲突
最佳实践:先在从库测试,使用监控工具,准备回滚方案。
Q4:MySQL 8.0在Online DDL方面有哪些重要改进?
text
复制
下载
答:MySQL 8.0的重要改进:
1. INSTANT算法:支持添加列等操作(8.0.12+)
2. 原子DDL:DDL操作要么完全成功,要么完全回滚
3. 并行DDL:支持并行创建索引(8.0.14+)
4. 更好的进度监控:通过performance_schema
5. DDL日志:避免DDL执行中的数据丢失
6. 更多的INPLACE操作:扩大了支持范围
这些改进大大提高了DDL的可靠性和性能。
这个完整的Online DDL三大算法解析,从基础原理到生产实践,涵盖了面试和工作中的各种场景,帮助你深入理解MySQL的DDL机制。