ddl是定义数据库结构的语言,负责建库建表、修改表结构等操作,不处理数据本身,且多数操作不可回滚。

DDL 是什么?建库建表时必须知道的“结构开关”
DDL(Data Definition Language)是定义数据库骨架的语言,它不碰数据本身,只管“有没有这张表”“字段叫什么”“主键在哪”。一旦执行 CREATE、ALTER、DROP,结构就变了,且多数操作不可回滚。
-
CREATE DATABASE IF NOT EXISTS db_name DEFAULT CHARSET utf8mb4;—— 加IF NOT EXISTS避免脚本重复执行报错 -
CREATE TABLE里别漏掉NOT NULL和DEFAULT,否则插入空值可能意外失败或存入0/'' -
TRUNCATE TABLE t1;比DELETE FROM t1;快得多,但会重置自增 ID,且无法加 WHERE 条件 -
ALTER TABLE修改列类型时,若已有数据不兼容新类型(比如把VARCHAR(10)改成CHAR(2)),MySQL 会直接报错ERROR 1265 (01000): Data truncated for column
DML 和 DQL 别混:增删改是 DML,查是 DQL
严格来说,SELECT 属于 DQL(Data Query Language),不是 DML。DML 只负责变更数据:INSERT、UPDATE、DELETE。这点在权限配置和 binlog 解析时特别关键——比如你只给用户 DML 权限,他连 SELECT 都不能执行。
-
INSERT INTO t1 (a,b) VALUES (1,'x'),(2,'y');—— 多行插入比循环单条快一个数量级,但注意 max_allowed_packet 限制 -
UPDATE t1 SET status = 1 WHERE id IN (SELECT id FROM tmp_ids);—— MySQL 8.0+ 支持,但老版本会报错You can't specify target table 't1' for update in FROM clause,得用 JOIN 绕过 -
DELETE FROM t1 LIMIT 1000;—— 加LIMIT防止误删全表;线上大表删除建议分批 + sleep,避免锁表太久 -
SELECT * FROM t1 WHERE name LIKE '%abc';—— 左模糊无法走索引,查得慢还容易拖垮连接数
DCL 权限控制:GRANT 不等于“给所有权限”
GRANT 和 REVOKE 管的是“谁能干什么”,不是功能开关。常见误区是以为 GRANT SELECT ON db.* TO 'u'@'%' 就能让用户连上数据库——其实他还需要 USAGE 权限(即连接权限),而这个权限是创建用户时自动赋予的;但若用 CREATE USER 单独建号,没显式 GRANT,就连不上。
- 生产环境禁止用
GRANT ALL PRIVILEGES,哪怕只给一个开发库;最小权限原则:只开SELECT, INSERT, UPDATE,禁用DROP和ALTER -
GRANT SELECT (id,name) ON db.t1 TO 'u'@'%';—— 列级授权,用户只能查这两列,其他字段返回NULL(需 MySQL 8.0+) - 权限修改后,记得执行
FLUSH PRIVILEGES;—— 大多数情况不用,但若直接改了mysql.user表,就必须刷
TCL 事务控制:COMMIT 前 rollback 才有效
TCL(Transaction Control Language)只对支持事务的引擎(如 InnoDB)生效,MyISAM 完全无视 BEGIN/COMMIT。而且事务边界很脆弱:客户端断连、超时、甚至某些 SQL 语句(如 DLL)会隐式触发 COMMIT。
-
START TRANSACTION;或BEGIN;后,所有后续 DML 都在同一个事务里,直到COMMIT或ROLLBACK -
SAVEPOINT sp1;+ROLLBACK TO sp1;可实现部分回滚,但嵌套太深会影响性能,也难维护 - 执行
CREATE TABLE、DROP TABLE后,当前事务会自动提交——这是很多人踩坑的地方:以为还能ROLLBACK,结果结构已变 - 长事务(>10s)会拖慢 purge 线程,堆积 undo log,严重时导致磁盘爆满;线上应监控
information_schema.INNODB_TRX表
DDL 的隐式提交、DQL 和 DML 的权限分离、TCL 在 DDL 前的失效点——这些不是冷知识,而是每天上线、迁移、排障时真实卡住人的地方。










