3.1 数据定义语言 DDL


3.1 数据定义语言 DDL

本节摘要:DDL 负责创建和修改库表结构,它的特殊之处在于改动的是"容器"而不是"内容",很多操作会触碰整张表。本节讲 CREATE、ALTER、DROP 的工程用法,重点拆解 MySQL 8.0 在线 DDL 的能力边界与 ALGORITHM 参数。位置:SQL 家族的第一站,为后面所有读写提供结构前提。

为什么 DDL 要单独当一节讲

增删改查的语句错了,改回来就行;DDL 错了,代价按分钟甚至小时计。评审会风险清单上,大表 DDL 永远排在前三:一张三千万行的订单表上执行一次需要重建的 ALTER,视机器配置可能锁写几分钟到几小时,主从延迟飙升,所有依赖这张表的业务跟着抖。理解 DDL 的正确姿势因此不是背语法,而是理解每条语句背后的执行代价

MySQL 8.0 的 InnoDB 支持在线 DDL,核心是两个参数:ALGORITHM=INPLACE 尽量在引擎内部完成、不复制全表;ALGORITHM=COPY 则要新建一张影子表复制全部数据再换名。同为"加一列",8.0 的 ALGORITHM=INSTANT 只改元数据、瞬间完成;而"改列类型"几乎总是 COPY。能力边界记一张简表就够:

操作 典型算法 线上风险
加列(末尾) INSTANT 极低,秒级
加索引 INPLACE 低,可并发 DML
改列类型 COPY 高,重建整表
缩短 VARCHAR 长度 视情况 中,需确认
DROP COLUMN INSTANT 或 INPLACE 中低
改字符集 COPY 高,全表重写

完整演练:从建库到给大表加字段

背景:订单系统上线,走一遍标准 DDL 流程;三个月后需求要给 orders 加"渠道来源"字段。操作分两幕。

第一幕,建库建表(注意每个语句携带的工程信息):

CREATE DATABASE mall DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; CREATE TABLE orders ( order_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, customer_id BIGINT UNSIGNED NOT NULL, amount DECIMAL(10,2) NOT NULL, status TINYINT NOT NULL DEFAULT 1, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, KEY idx_customer (customer_id, created_at) ) ENGINE=InnoDB COMMENT '订单主表';

几个细节:字符集在建库时统一声明,表自动继承,避免"有的表 utf8 有的表 latin1"的漂移;idx_customer 是复合索引,先按客户查再看时间,覆盖"查某人最近订单"这个最高频访问模式——索引设计方法论第 4 章展开,这里先让结构带着正确索引上线。

第二幕,三个月后加字段:

ALTER TABLE orders ADD COLUMN channel TINYINT NOT NULL DEFAULT 0 COMMENT '来源渠道', ALGORITHM=INSTANT; -- 结果:Query OK, 0 rows affected(秒级完成)

结果与解读:8.0 的加列默认走 INSTANT,元数据修改即刻完成,存量行读该列时按默认值补齐,未写满的页延后物化。这是 8.0 相对 5.7 最实用的改进之一。变式一:如果是 5.7 环境,加列是 INPLACE,加一列到末尾通常仍可在线执行,但数据量大时 IO 压力不可忽视,应挂低峰期执行并监控主从延迟。变式二:若需求是"把 amount 从 DECIMAL(10,2) 改成 DECIMAL(12,2)",则必须评估 COPY 代价,标准做法是借助 gh-ost 或 pt-online-schema-change 这类在线改表工具,用触发器或 binlog 回放的方式慢慢搬迁,不阻塞业务。

DROP 与 TRUNCATE:两句都要三思的命令

DROP 连表带结构一起删;TRUNCATE 保留结构清空数据,且不走逐行删除、不触发触发器、通常不可回滚。评审会上对这两条命令的标准追问是:"在哪个环境执行?有没有备份?影响行数是全表吗?"生产惯例:高危语句一律先在测试环境演练,生产执行时用 WHERE 限定影响范围的 DELETE 替代无条件的 TRUNCATE,或者走工单审批双人复核。

易错点与评审清单

  • 把 DDL 混进业务事务:部分 DDL 会隐式提交当前事务,把结构变更和数据修改写在一个大事务里是典型的自埋雷;
  • 改名用 DROP 加 CREATE:该用 RENAME TABLE,原子操作,毫秒级;先删后建中间的服务中断窗口是纯事故;
  • 忘写 COMMENT:结构即文档,注释缺失意味着半年后每个字段都要考古;
  • 不加 ALGORITHM 就对大表执行 ALTER:默认行为可能退化为 COPY,执行前先 EXPLAIN 一下 DDL 本身(用 ALGORITHM=INPLACE 试探,失败会报错而不会执行)确认代价。

评审追问集:DDL 的三个深水问题

追问一:INSTANT 加列有限制吗? 有,且限制常被忽略。INSTANT 只支持在列末尾追加(或指定 AFTER 到某个位置,8.0.29 起才放开任意位置);列带非空约束时必须给默认值;同时做"加列又加索引"这类组合动作会整体降级到 INPLACE。实操建议:把 DDL 拆开执行——先走 INSTANT 的加列,再单独加索引,每步的风险档位都最优化。

追问二:DDL 会不会造成主从延迟? 会,而且是主从延迟的头号来源之一。COPY 类 DDL 在主库慢慢搬数据,binlog 里记录的是搬完的结果,从库重放同样要搬一遍;INPLACE 加索引期间产生的增量写入也在堆重放队列。所以大表 DDL 的监控清单里必须有从库延迟曲线,执行窗口选在延迟低谷期,必要时暂停非关键从库的重放避免读流量异常。

追问三:上线 DDL 的工单里必须写清什么? 五项缺一不可:目标表与当前行数、执行算法与预估时长、是否影响主从延迟、回滚方案(多数 DDL 的回滚是反向 DDL,同样要评估代价)、执行窗口与值班人。评审会上看到"待定"字样出现在任何一项,这张工单就退回。DDL 的事故几乎都出在信息不全的工单上,把信息写全本身就是一次风险自查。

要点回顾:DDL 改的是容器,代价按整表计;8.0 的 INSTANT/INPLACE/COPY 三档决定线上风险等级;大表改结构走在线工具或低峰窗口;RENAME 替代先删后建;DDL 工单五要素写全才算评审通过。结构就位,下一节往表里放数据、取数据。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U