在MySQL数据库运维中,表结构变更(DDL)是常见的操作需求,但对于千万级甚至亿级的大表,传统的ALTER TABLE
操作可能引发长时间锁表,导致业务中断或性能雪崩。
如何在不影响业务的前提下安全执行DDL?今天从实战角度出发,给大家深入剖析原生Online DDL与PT-OSC(Percona Toolkit Online Schema Change)两大无锁变更方案,结合具体示例与避坑指南,助你轻松应对大表结构变更难题。
MySQL 5.6+的Online DDL通过ALGORITHM=INPLACE
和LOCK=NONE
参数实现“原地修改”,避免全表拷贝。
Copy方式简单过程:首先按照原表定义创建一个新的临时表,然后对原表加写锁(禁止DML,允许select),接着在步骤1创建的临时表执行 DDL,然后将原表中的数据copy到临时表,最后释放原表的写锁将原表删除,并将临时表重命名为原表
其核心流程分为三个阶段:
场景1:添加二级索引
ALTER TABLE user_order ADD INDEX idx_user_id (user_id), ALGORITHM=INPLACE, LOCK=NONE;
优势:无需重建表,仅修改元数据,允许并发DML操作。
场景2:扩展VARCHAR列长度
ALTER TABLE product MODIFY description VARCHAR(500), ALGORITHM=INPLACE, LOCK=NONE;
限制:VARCHAR列所需的长度字节数必须保持不变。0~255需要一个字节来编码值,大于等256需要两个字节来编码。使用In Place ALTER TABLE只支持将VARCHAR列大小从0到255字节增加,或从256字节增加到更大的大小。反之需要使用ALGORITHM=COPY才可以。
pt-osc 主要用于修改表时不锁表,简单地说,首先创建一个与原始表一样的新的空表,并根据需要更改表结构,因为是空表修改表结构速度会非常快,然后将原始表中的数据以小块形式复制到新表中,接着删除原始表,最后将新表重命名为原始名称。在复制过程中,对原始表的所有新的更改(insert,delete,update)都将应用于新表,因为在原始表上创建了一个触发器,以确保所有新的更改都将应用于新表。
PT-OSC通过影子表+触发器实现无锁变更:
_table_new
); 场景1:修改列类型(如CHAR转VARCHAR)
pt-online-schema-change --alter "MODIFY c VARCHAR(200) NOT NULL DEFAULT ''" \
--user=admin --password=*** --host=127.0.0.1 --port=3306 \
--execute D=testdb,t=user_info --no-check-alter
说明:需确保原表有主键,且新列允许NULL或指定默认值。
场景2:删除外键约束
pt-online-schema-change --alter "DROP FOREIGN KEY _fk_order_user" \
--alter-foreign-keys-method=rebuild_constraints \
--user=admin --password=*** --execute D=testdb,t=order
关键参数:--alter-foreign-keys-method
处理外键依赖,优先选择rebuild_constraints
重建约束。
场景:需同时添加索引并修改列类型。
--max-load
和--max-lag
控制负载,避免拖垮数据库。 Innodb_rows_read
和锁等待时间。 tmpdir
需足够存放临时文件。 --alter-foreign-keys-method
,否则任务失败。 总结:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。