MySQL vs 达梦:新增字段为何前者锁表后者却不会?
MySQL vs 达梦:新增字段为何前者锁表后者却不会?
在数据库日常运维中,表结构变更(DDL)是高频操作,而“新增字段”作为最常见的DDL之一,却在MySQL和达梦(DM)两款数据库中表现出截然不同的锁表行为——MySQL新增字段常触发锁表导致业务阻塞,达梦却能近乎无感执行。本文从存储引擎、DDL执行机制、锁策略三个核心维度,拆解二者差异的底层逻辑。
一、核心现象:新增字段的锁表差异
先明确核心现象:
- MySQL:InnoDB引擎下执行
ALTER TABLE t ADD COLUMN col INT;时,会对目标表加元数据锁(MDL),且多数场景下需等待表上所有读写操作完成,期间表无法被读写,业务请求会阻塞直至DDL完成或超时。 - 达梦(DM):执行
ALTER TABLE t ADD COLUMN col INT;时,几乎不阻塞业务读写,仅在极短时间内持有表级锁,业务无感知。
这种差异并非“MySQL设计缺陷”,而是两款数据库在“存储引擎架构”“DDL实现策略”上的底层选择不同。
二、MySQL新增字段锁表的底层原因
MySQL的锁表行为核心源于InnoDB引擎的DDL执行机制和元数据锁(MDL) 的双重约束,具体可拆解为3个关键点:
1. 元数据锁(MDL)的强管控
MySQL 5.5及以上版本引入MDL,用于保证表元数据的一致性:
- 当执行
ALTER TABLE时,MySQL会先申请MDL_EXCLUSIVE(排他)锁,该锁与表上的读锁(MDL_SHARED_READ)、写锁(MDL_SHARED_WRITE)互斥; - 申请排他锁前,需等待表上所有已存在的读写操作释放MDL锁,且等待期间会阻塞后续所有新的读写请求;
- 若表上有长事务(如未提交的查询、更新),DDL会一直等待,最终导致业务请求排队阻塞,表现为“锁表”。
2. InnoDB的DDL执行模式(Copy Table)
InnoDB对“新增字段”这类DDL的默认处理逻辑是“拷贝表+替换”:
- 创建一个新的临时表,结构为原表+新增字段;
- 将原表数据逐行拷贝到临时表;
- 持有排他MDL锁,原子化替换原表与临时表的名称;
- 删除原表,完成字段新增。
整个过程中,拷贝数据阶段虽不持有排他锁,但最终替换表的步骤必须持有排他MDL锁,且拷贝数据的耗时与表数据量正相关——数据量越大,排他锁等待时间越长,锁表越明显。
3. 例外:MySQL 8.0的Online DDL优化
MySQL 8.0对部分DDL做了Online优化(如新增非主键字段),无需全表拷贝,仅修改表元数据,锁表时间大幅缩短,但仍需短暂持有排他MDL锁;若新增字段涉及默认值(如DEFAULT 'xxx')或主键变更,仍会触发全表拷贝,锁表问题依旧。
三、达梦数据库不锁表的核心逻辑
达梦作为国产数据库,在DDL设计上更侧重“业务无感知”,其核心优势源于存储架构和DDL原子化设计:
1. 达梦的存储架构:行存储+增量日志
达梦默认采用行存储引擎,且对表元数据的修改采用“增量记录”模式:
- 新增字段时,仅在表的元数据字典中添加字段定义,无需拷贝全表数据;
- 历史数据行默认不存储新增字段的值(读取时返回NULL或默认值),新写入数据行才包含该字段,从根本上避免了“拷贝表”的耗时操作。
2. DDL执行的“低锁级+短持有”策略
达梦对DDL的锁策略做了极致优化:
- 新增字段仅需申请表级共享锁(S锁),而非排他锁,共享锁与业务读写操作(行级锁)兼容,不会阻塞正常业务;
- 仅在修改元数据字典的最后阶段,短暂持有表级排他锁(X锁),耗时仅毫秒级,业务无感知;
- 达梦的DDL操作基于“原子化日志”实现,即使DDL执行中断,也可通过日志回滚,无需长时间锁表保证一致性。
3. 达梦的Online DDL:全场景支持
达梦对所有常规DDL(新增字段、修改字段类型、索引变更)均实现了Online化:
- 无需依赖“临时表拷贝”,所有元数据修改均在原表上增量完成;
- 读写操作与DDL操作并行执行,仅通过行版本控制(MVCC)保证数据一致性,彻底避免锁表。
四、核心差异对比表
| 维度 | MySQL(InnoDB) | 达梦数据库 |
|---|---|---|
| 锁类型 | 排他MDL锁(长时间持有) | 共享表锁+短暂排他锁(毫秒级) |
| DDL执行方式 | 多数场景需拷贝全表(8.0部分优化) | 仅修改元数据,无需拷贝表 |
| 数据一致性保障 | 依赖MDL锁+表拷贝 | 依赖MVCC+原子化日志 |
| 业务影响 | 数据量大时锁表阻塞读写 | 无感知,读写不受影响 |
| 适用场景 | 小表/低并发场景,8.0优化后可支持中表 | 大表/高并发场景,核心业务无中断需求 |
五、实践建议
1. MySQL新增字段避坑方案
- 优先升级至MySQL 8.0,利用Online DDL优化;
- 避免在业务高峰期执行DDL,选择低峰期操作;
- 新增字段时避免设置默认值(如
DEFAULT 'xxx'),减少全表拷贝; - 大表新增字段可采用“分批次”方案:先新增字段(无默认值),再分批更新默认值,最后修改字段默认值。
2. 达梦数据库使用注意
- 达梦虽不锁表,但新增字段后需注意历史数据的读取逻辑(如NULL值处理);
- 高并发下执行DDL前,建议先确认无长事务,避免极短的排他锁等待导致短暂阻塞。
六、总结
MySQL新增字段锁表的核心是MDL排他锁+全表拷贝,本质是InnoDB引擎为保证元数据一致性的折中方案;而达梦不锁表则源于元数据增量修改+低锁级短持有+MVCC并行控制的设计,更适配高并发业务场景。
二者的差异并非“优劣之分”,而是设计目标不同:MySQL侧重“底层架构简洁+兼容性”,达梦侧重“业务连续性+国产化适配”。在实际选型和运维中,需根据业务场景(数据量、并发量、可用性要求)选择合适的数据库,并针对性优化DDL操作。
更多推荐




所有评论(0)