新闻详情

新闻详情

首页 / 资讯中心 / 详情

MySQL入门:DDL与DML实操详解,建表改表与数据操作避坑指南

发布时间:2026/10/2 14:28:55来源:尧图网络
MySQL入门:DDL与DML实操详解,建表改表与数据操作避坑指南
作为一个常年帮人救火MySQL、也带过不少新人的老家伙我太清楚新手入门最容易被什么东西劝退了。很多人一上来就背了一堆概念结果真到了命令行连建个表都颤颤巍巍更别提后面改结构、插数据时踩的满地坑。这个MySQL学习系列的第一篇我就直接挑最基础的DDL和DML下手把这俩概念彻底掰扯清楚然后全程敲命令实操一遍把那些网上教程不会明说的陷阱和心得也一并抖出来。这篇内容适合刚接触MySQL的纯新人也适合那些用了很久MySQL但始终靠Navicat点点点、没系统捋过底层逻辑的朋友。看完你至少能明白你每天在客户端里做的那些操作到底哪些算DDL哪些算DML以及为什么有的操作能撤销、有的操作一执行就再也回不了头。1. 为什么新手总把DDL和DML混为一谈很多新手上来就问DDL和DML到底有啥区别不都是SQL吗我觉得他们混在一起很正常因为这俩术语的英文全称长得太像而且都归类在SQL大伞下面。但你要是搞不清这俩的区别后面遇到为什么这条DELETE能回滚那条TRUNCATE却直接清空了这种问题就会一头雾水。1.1 DDL和DML的分界线结构还是数据先把定义摆清楚。DDL是Data Definition Language数据定义语言操作对象是数据库的结构——库、表、索引、视图这些容器本身。DML是Data Manipulation Language数据操作语言操作对象是数据——表里存的一行一行记录。两者的分界线特别朴素你是在造容器还是在往容器里放东西。用厨房来打个比方。DDL像是你买菜谱、买锅、切菜配菜——你是在定义这顿饭要做成什么样锅碗瓢盆就是表结构、字段类型、索引。DML才是真的开火炒菜吃菜——每一铲子下去锅里的食材数据在变化。你不可能在炒菜的过程里突然把锅给换了形状还指望菜不糊同样你也不能在业务跑得好好的时候肆无忌惮地改表结构这俩天然就是两种节奏。MySQL官方文档里有一张表把常用命令归了类类别命令操作对象DDLCREATE、ALTER、DROP、TRUNCATE、RENAME库、表、索引、视图等DMLINSERT、UPDATE、DELETE、SELECT表数据DCLGRANT、REVOKE用户权限有意思的是SELECT在MySQL的官方分类里被归到了DML这跟很多教材上把SELECT单独标成DQL数据查询语言不太一样。我的建议是考试按教材实操按MySQL官方来反正你写代码的时候又不用管它叫DQL还是DML。1.2 一个被忽略的关键差异能不能回滚这是我认为DDL和DML之间最要命的区别很多人栽跟头就栽在这。DML默认受事务控制。什么意思例如你执行了DELETE FROM user WHERE id 10086;如果这行还没COMMIT你反悔了大可以ROLLBACK数据原封不动地回来。事务就像给DML操作装了个后悔药。DDL默认自动提交且不可回滚。CREATE TABLE、ALTER TABLE、DROP TABLE这类命令一执行MySQL立刻帮你隐式地把当前事务提交了之后想ROLLBACK门都没有。这也是为什么生产环境里执行DROP TABLE之前我总会反反复复确认三遍实在不行就先用RENAME把表改成table_bak_20250101观察几天没问题再真正DROP。1.3 先说结论这篇内容你要带走什么别小看DDL和DML到底有什么区别这个问题它直接决定了你后面这两大类的操作要遵守完全不同的纪律学习重心不同DDL重在设计DML重在操作。风险意识不同DDL要极度谨慎结构一变影响全局DML只需小心WHERE条件。恢复手段不同DML能靠事务回滚兜底DDL只能靠备份。把这条主线和厨房类比记在脑子里接下来我们直接上命令。2. DDL实操建库、建表、改表结构一次过完既然分清了概念我们就从最正统的DDL开始。我默认你本地已经装好了MySQL 8.0装啥版本都行语法基本通用能打开mysql命令行或者用客户端工具连上去。2.1 建库字符集和排序规则的选择经验建库的语法本身非常简单CREATE DATABASE if NOT EXISTS school DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;我从实战角度解释一下这里为什么这么写。先说if NOT EXISTS这个纯属习惯。脚本二次执行的时候不会因为库已存在而报错这种写法在初始化脚本里几乎是标配能省不少事。如果你要建的库已经存在但又想直接覆盖那要么先DROP DATABASE要么ALTER。不过注意DROP DATABASE同样不可回滚慎用。再说utf8mb4字符集。现在已经是2025年了数据库新建库默认字符集请无脑选utf8mb4。它比你以前可能见过的utf8更完整能存储所有Unicode字符包括emoji。很多老系统因为历史原因还是utf8mb3在MySQL里别名utf8导致插入生僻字或emoji时报Incorrect string value这种问题都快成MySQL排错经典名场面了。既然是新库一步到位别再给后人留坑。排序规则utf8mb4_unicode_ci也要注意。ci结尾代表case insensitive也就是大小写不敏感的比较。对于英文字母的排序、比较来说这符合大多数业务直觉。8.0默认的utf8mb4_0900_ai_ci也可以但既然要追求通用、兼容老版本我个人保守选择utf8mb4_unicode_ci。2.2 建表一条CREATE TABLE拆开揉碎建表是整个DDL里头最核心的活因为结构设计得好不好决定了三年后你维护起来是想摔键盘还是想感谢当年的自己。先看一条完整的建表语句CREATE TABLE student ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 主键ID, student_no VARCHAR(32) NOT NULL COMMENT 学号, name VARCHAR(32) NOT NULL COMMENT 姓名, gender TINYINT NOT NULL DEFAULT 0 COMMENT 性别: 0未知 1男 2女, birthday DATE DEFAULT NULL COMMENT 出生日期, phone VARCHAR(20) DEFAULT NULL COMMENT 手机号, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY uk_student_no (student_no), KEY idx_name (name) ) ENGINE InnoDB DEFAULT CHARSET utf8mb4 COMMENT 学生表;这语句值得一行一行看。NOT NULL和DEFAULT组合是为了防止程序漏传字段导致插入失败或产生脏数据COMMENT给字段加注释这是老团队协作的基本素养没有注释的表三个月后连你自己都看不懂字段含义。AUTO_INCREMENT实现自增主键PRIMARY KEY定义主键UNIQUE KEY保证学号唯一KEY是创建普通索引。这里特别说明两个点。第一ON UPDATE CURRENT_TIMESTAMP很有用。每次更新该行时update_time字段会自动更新成当前时间省得在应用层手动维护最后修改时间这种字段。代价是每次UPDATE都会多一点点开销但换来的是审计和排查问题的巨大便利。第二主键我用了BIGINT UNSIGNED自增而不是直接用student_no学号当主键。业务主键学号和数据库主键自增ID分开是很多公司研发规范里的默认要求。因为学号理论上可能变更转学、重号合并而自增ID纯内部使用不依赖任何业务规则不易出幺蛾子。2.3 改表ALTER TABLE的高频玩法与锁表风险建表是一锤子买卖改表才是日常工作。ALTER TABLE有四类操作必须熟练。新增字段ALTER TABLE student ADD COLUMN email VARCHAR(64) DEFAULT NULL COMMENT 邮箱 AFTER phone;AFTER可以控制新字段加在哪不写默认加在最后。如果你不想动老表字段顺序就乖乖放最后。修改字段类型或属性ALTER TABLE student MODIFY COLUMN phone VARCHAR(32) NOT NULL DEFAULT COMMENT 手机号;MODIFY COLUMN用来改字段类型、默认值、注释。注意它会覆盖你写的所有属性比如你只想改注释结果没写NOT NULL那原来的非空约束可能就没了。所以MODIFY时必须把整字段的完整定义写全。重命名字段ALTER TABLE student CHANGE COLUMN name student_name VARCHAR(32) NOT NULL COMMENT 学生姓名;CHANGE COLUMN和MODIFY的区别在于它可以改名而MODIFY不行。CHANGE的语法是旧名 新名 类型定义类型定义也照样要完整写。删除字段ALTER TABLE student DROP COLUMN email;删字段不可逆要是删错了只能靠备份恢复所以执行前建议确认有没有程序还在引用这个字段最好先去代码里搜一遍。这里必须重点强调一个DDL的坑ALTER TABLE在MySQL 5.7及更早版本里修改表结构时很多操作会锁表期间所有对这个表的DML操作都会被阻塞。例如要给一张千万行的大表ADD COLUMN跑几分钟的期间业务写入全堵住用户反馈就是系统卡死了。MySQL 8.0做了优化部分DDL操作支持ALGORITHMINSTANT比如ADD COLUMN在8.0.12以后往往毫秒级完成。但MODIFY COLUMN、CHANGE COLUMN这类操作依然可能需要COPY或INPLACE。在生产环境动大表之前我的经验是先看数据量再说方案。方案无非三种低峰期直接ALTER比如凌晨两点。用gh-ost、pt-online-schema-change这类工具做在线DDL原理是搞一张影子表一点点把数据拷过去最后切换表名。业务侧平滑过渡先加可空字段程序兼容再慢慢填充数据最后收紧约束。2.4 删表DROP、TRUNCATE、DELETE别搞混删数据或删表这个动作最容易暴露一个人对DDL/DML理解的深浅。操作分类能不能加WHERE能不能回滚是否保留表结构是否重置自增IDDELETEDML能事务内能回滚保留不重置TRUNCATEDDL不能不能回滚保留重置DROPDDL不能不能回滚删除整个表没了很多人以为DELETE和TRUNCATE只是快和慢的区别其实它们分属不同阵营。TRUNCATE在MySQL官方定义里属于DDL因为它隐式提交、不可回滚并且会释放表空间、把自增计数器重置为初始值。DELETE则是纯粹的行级DML操作走了事务可以按WHERE筛选删完自增ID接着涨。我见过一次事故有人想清空一张测试表为了快用了TRUNCATE结果那表是生产环境的配置表而且没备份。TRUNCATE在InnoDB里可以通过FUN --incremental方式部分恢复不实际上TRUNCATE是直接用新表替换旧表旧表空间被释放了常规手段根本恢复不了。最后团队从binlog一条条捞日志折腾了一整天才补回来一部分配置。所以记住一句口诀能DELETE就DELETETRUNCATE只用来清垃圾表DROP只用来删废弃表。3. 建表设计里的取舍字段类型、约束与索引到了这一步建表的语法你已经完全能写了但设计表的时候最让人纠结的从来不是语法而是这个字段用什么类型要不要建索引。这一节我把经验沉淀下来每一句话背后基本都是血泪。3.1 字段类型四大家族选错类型是灾难的开始MySQL的字段类型大体分四类选类型的核心原则是尽量精确够用即可远离模糊。整数类型TINYINT、SMALLINT、INT、BIGINT。能用TINYINT表示性别、状态就不要用INT能省不少空间。BIGINT UNSIGNED给主键留着因为业务量一大INT的上限21.47亿真的可能被撞穿。小数类型FLOAT、DOUBLE、DECIMAL。核心铁律钱相关的字段一律用DECIMAL永远不要用FLOAT/DOUBLE。FLOAT/DOUBLE是二进制浮点数存0.1这种十进制的数字会有精度损失。你存了9.99算了一顿账后可能是9.98999999最后对账对不上。DECIMAL是十进制定点数允许指定精度比如DECIMAL(10,2)表示总共10位小数点后保留2位对金额足够又精确。这个坑我见得太多了做支付、商城系统的都懂。字符串类型CHAR、VARCHAR、TEXT。CHAR定长VARCHAR变长。日常业务字段我几乎全用VARCHAR因为它在存储时会根据实际长度调整占用空间。但CHAR在某些场景更好比如MD5哈希、手机号这类固定长度的字段CHAR反而更快且没有碎片。TEXT能别用就别用它的行溢出处理会让查询变慢而且不能有默认值在8.0里也有一堆限制。真有大段内容的场景考虑拆表或者用文件存储。日期时间类型DATE、DATETIME、TIMESTAMP。DATE只存年月日适合生日。DATETIME范围是1000年到9999年跟时区无关。TIMESTAMP范围只有1970到2038年跟时区相关它会在存储时转换成UTC取出时转回当前时区。我个人99%的情况下推荐DATETIME因为排查问题时直观看得懂不会有时区错乱。TIMESTAMP有2038年问题很多老系统到时候会遭殃。3.2 约束让数据库替你守住数据底线约束就是规则主键约束、非空约束、唯一约束、默认值约束、外键约束。我逐条说心得。主键约束一张表必须有主键这是底线。没有主键的表在InnoDB里会生成隐藏主键你连数据都定位不准。自增BIGINT主键是最省心的方案。非空约束NOT NULL应该是绝大多数业务字段的默认状态。允许为NULL的字段在索引、比较、聚合时都有额外的坑。比如COUNT(*)会统计NULL行但COUNT(phone)不会统计NULL逻辑不一致会把人绕晕。能用空字符串表示没有的就不要用NULL表示不知道。唯一约束像学号、身份证号这种业务上必须唯一的字段直接建UNIQUE KEY让数据库兜底。这样哪怕应用层有并发漏洞数据库也能拦住重复数据。但注意有唯一索引的表批量INSERT时要小心重复键冲突后文DML部分会讲怎么优雅处理。默认值约束DEFAULT值的精髓在于给那些大部分情况同一个值的字段设置合理默认值程序可以少传参数。比如状态字段默认0创建时间默认CURRENT_TIMESTAMP。有个常见坑是TIMESTAMP/DATETIME的默认值在MySQL 5.6.5之前不能让函数当表达式但8.0已经很宽松了直接用CURRENT_TIMESTAMP没问题。外键约束这是我最想劝退的东西。很多单机时代的教科书让你建外键保证引用的完整性但在实际高并发互联网业务中外键带来的额外检查开销、死锁风险、以及分库分表时的迁移动辄失败让很多大厂研发规范直接禁止使用物理外键。数据完整性由应用层把关数据库层只负责存储和索引。你面试可以说外键写代码慎用外键。3.3 索引查询快慢的胜负手但别乱加索引是DDL里最影响性能的部分原理上像书的目录没有索引就得全表扫全表扫就是逐行翻。建索引的原则我用三句话概括区分度高的列才值得建索引。性别这种只有两三个值的列建索引也没啥用优化器大概率不走索引。查询条件里频繁出现的列组合成联合索引。例如WHERE里经常同时用到school_id和class_id就建立(school_id, class_id)联合索引。注意最左前缀原则联合索引的生效是从最左边开始的(school_id, class_id)索引只能覆盖school_id单独查或者school_id class_id查但不能直接服务只有class_id的查询。索引不是越多越好。每个索引在写入时都要更新B树结构索引太多会让INSERT/UPDATE/DELETE变慢。一张表我一般控制在5个以内只给热门的查询路径建。所以建索引的正确姿势是先看慢查询日志发现哪条SQL慢了再结合执行计划的type、key字段判断要不要加索引而不是建表时拍脑袋把每个字段都建一遍。3.4 一个接近真实业务的建表演练我们把上面所有原则串起来模拟一张电商订单表的建表CREATE TABLE order_info ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 订单ID, order_no VARCHAR(32) NOT NULL COMMENT 订单号, user_id BIGINT UNSIGNED NOT NULL COMMENT 用户ID, shop_id BIGINT UNSIGNED NOT NULL COMMENT 店铺ID, amount DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT 订单金额, status TINYINT NOT NULL DEFAULT 0 COMMENT 订单状态: 0待支付 1已支付 2已发货 3已完成 4已取消, pay_time DATETIME DEFAULT NULL COMMENT 支付时间, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY uk_order_no (order_no), KEY idx_user_status (user_id, status), KEY idx_shop_status (shop_id, status) ) ENGINE InnoDB DEFAULT CHARSET utf8mb4 COMMENT 订单表;注意amount就是DECIMALorder_no给了唯一索引user_id、status建了联合索引可以支撑查某个用户某状态的订单这种最高频的查询同时不重复建单列索引避免浪费存储和写入开销。这套设计足够撑起一个中小型订单系统的起步阶段。4. DML实操INSERT、UPDATE、DELETE、SELECT的细节与坑表结构搞定接下来就是在表里搬砖。DML这部分大家天天在写但很多隐蔽的问题恰恰就藏在最熟悉的操作里。4.1 INSERT批量插入和两个高级语法插入数据是最简单的但写法好坏影响很大。单条插入INSERT INTO student (student_no, name, gender, birthday, phone) VALUES (2025001, 张三, 1, 2005-06-15, 13800000001);字段列表建议写明不要省略。省略默认按全字段顺序一旦后来表结构调整加了新字段你这句SQL就会炸。批量插入INSERT INTO student (student_no, name, gender) VALUES (2025002, 李四, 2), (2025003, 王五, 1), (2025004, 赵六, 1);一次INSERT多行的效率远高于循环逐条插入关键原因是减少客户端和数据库的交互次数。实测中批量插入1000行比单条循环1000次能快一到两个数量级。两个高级语法INSERT IGNORE和ON DUPLICATE KEY UPDATE。数据导入场景里一张表有唯一键你没法保证每一行都不重复这时候INSERT IGNORE遇到唯一键冲突就悄悄忽略这一行不报错继续插后面的。适合只要新数据重复数据不要的场景。INSERT IGNORE INTO student (student_no, name) VALUES (2025001, 张三副本);ON DUPLICATE KEY UPDATE遇到唯一键冲突就改成更新。适合有就更新没有就插入的幂等写场景。INSERT INTO student (student_no, name, phone) VALUES (2025001, 张三, 13900000001) ON DUPLICATE KEY UPDATE phone VALUES(phone);注意在MySQL 8.0.20之后VALUES()函数在ON DUPLICATE KEY UPDATE里被标记为弃用推荐用别名语法INSERT INTO student (student_no, name, phone) VALUES (2025001, 张三, 13900000001) AS new ON DUPLICATE KEY UPDATE phone new.phone;这种写法能少两道程序逻辑判断数据库帮你把到底插还是更这块烫手山芋接住了。4.2 UPDATE不带WHERE就是生产事故现场UPDATE是DML里风险最高的一句SQL没有之一。因为MySQL默认没有强制UPDATE必须带WHERE语法上允许你全表更新。最典型的事故场景程序员想改某一条数据凭印象写了UPDATE student SET phone 13900000000 WHERE name 张三;结果表里有三个叫张三的同学手机号全被改了。更惨的是有人漏了WHEREUPDATE student SET status 1;这一句下去全表状态全变1。执行前没有备份、没有事务包裹、直接连生产库……这种故事每年都在各个公司上演。防护意识必须刻进DNA里我建议操作前先SELECT。你要UPDATE的数据先用同样的WHERE条件跑一遍SELECT看清楚到底会命中多少行。用事务包起来执行。先BEGIN;然后UPDATE再SELECT核实影响行数确认无误再COMMIT有问题直接ROLLBACK。设置安全模式。在mysql命令行或客户端连接加上--safe-updates选项它会强制要求UPDATE/DELETE带WHERE并且WHERE要基于索引列。实测这一招能救很多新手一命。4.3 DELETE删除数据的正确姿势DELETE和UPDATE一样防呆核心也是WHERE。但DELETE还要面对一个实际问题删除大表数据不要太狠。一条DELETE如果一次性删几十万行会持有大量行锁和事务日志甚至可能把binlog撑爆、把主从延迟拉高。性能良好的做法是分批次删DELETE FROM order_info WHERE status 4 AND create_time 2024-01-01 LIMIT 1000;循环执行这句话直到影响行数为0。每批只删1000行锁持续时间短事务日志量小对线上影响小得多。你要是直接一次全删删的时候别的业务写入全被阻塞搞不好还要被DBA叫去喝茶。如果业务需求是清空一张表但保留表结构到底用DELETE还是TRUNCATE回到第2节的结论从数据安全性角度优先DELETE如果确定这表里全是垃圾数据、不需要回滚、还要重置自增ID那就TRUNCATE它比DELETE全表快得多。4.4 SELECTDML里的高频操作先搭骨架SELECT是天天用的我没有办法在一篇入门里把查询讲完但你可以先把骨架搭起来。一个查询的完整结构大致是SELECT 字段 FROM 表 WHERE 条件 GROUP BY 分组字段 HAVING 分组后的过滤条件 ORDER BY 排序字段 LIMIT 分页;执行顺序上实际运行时不是按你写的顺序来。数据库先FROM锁定表再WHERE过滤行再GROUP BY分组再HAVING过滤组然后SELECT求值再ORDER BY排序最后LIMIT截取。理解这个顺序你就能解释为什么WHERE里不能用SELECT里定义的别名而HAVING可以这类问题。新手最常踩的坑之一是分页SELECT * FROM student ORDER BY id LIMIT 100000, 20;这种深分页在数据量大时奇慢无比因为数据库会扫描前面10万行再扔掉。更优的写法是通过主键或唯一键做游标SELECT * FROM student WHERE id 100000 ORDER BY id LIMIT 20;这两条SQL表面效果相似但执行性能天壤之别。越是简单的操作越要琢磨底层执行逻辑这是DBA的基本功。5. DDL和DML联手锁与事务的初学者避坑指南到这里你已经知道DDL管结构、DML管数据了但现实世界里这两者不是各自独立的它们在一张表上会互相影响。最直接的桥梁就是锁和事务。5.1 事务DML被ACID管着DDL却免疫DML操作默认是由事务引擎InnoDB管理的所以它天然享受事务四个特性原子性、一致性、隔离性、持久性也就是ACID。原子性好理解一个事务里要么全部成功要么全部失败。比如转账的扣款和入账就是同一个事务里的两条UPDATE任何一条失败整个事务回滚钱不会凭空消失。隔离性值得多说一句。多个事务同时操作同一批数据会出现脏读、不可重复读、幻读。MySQL提供了四种隔离级别默认是可重复读REPEATABLE READ它配合MVCC多版本并发控制机制能保证同一事务里多次SELECT结果一致。这听起来很高级但你只需要知道一点在可重复读下行锁的具体表现是什么。而DDL就完全不一样了。前面反复强调DDL会自动提交事务它根本不受事务保护。所以你要是把ALTER TABLE放在事务里想出错回滚那是不可能的。事务还没开始或已开始都会被打断。这在开发中偶尔会踩到一个事务里先做了几条UPDATE想接着建个临时表结果建表语句一执行前面没提交的UPDATE全被隐式提交了后面回滚也回不掉。5.2 行锁与表锁并发DML的隐形规则MySQL的InnoDB引擎在并发控制上主要靠锁。默认情况下UPDATE、DELETE操作会在命中行上加行锁没命中的行其他事务正常操作。但有个经典陷阱UPDATE或DELETE的WHERE条件如果没有走索引InnoDB会从行锁升级为锁全表。因为引擎找不到精确的行只能把所有匹配扫描范围的行锁住本质等于大范围或全表锁。表现就是一条慢UPDATE一执行全表写入全卡住数据库连接数蹭蹭上涨。实战中的体会是凡是要做精确更新的条件列一定要有索引哪怕只是个普通索引。例如WHERE user_id ?若user_id建了索引只锁那一小段没索引整个表都堵住。这也是为什么前面建表时强调给高频查询列建索引——不仅查询快还避免锁升级。5.3 元数据锁DDL阻塞DML的真实事故复盘最后分享一个我亲身经历的事故它能让你明白DDL和DML在真实生产环境里是怎么掐架的。有一次业务方说线上订单查询突然全部超时。我上去一看数据库线程里大量SQL处在Waiting for table metadata lock状态。追到底发现有个程序员在凌晨跑了一个ALTER TABLE想给订单表加个字段结果他忘了提交事务可能是在客户端里先执行了某个SELECT或UPDATE没COMMIT也没关会话。这个没提交的事务一直持有订单表的元数据锁MDL读锁。而ALTER TABLE需要获取MDL写锁于是排在他后面的DDL一直等。更致命的是后续所有连接对这张表的增删改查也在排队等这个MDL读锁。一个不起眼的未提交事务拖垮了整张订单表的所有请求。复盘教训有三条大表DDL务必在低峰期做并且先确认没有长事务。执行ALTER前查一下当前活跃事务SELECT * FROM information_schema.innodb_trx;确认没有长时间未提交的事务。改表操作设置超时时间比如SET SESSION MAX_EXECUTION_TIME 30000;没改完就主动放弃别让DDL无限期等下去。这些都是我在一线踩过坑之后总结出来的。DDL和DML一个是设计师一个是搬砖工看似分工明确但在共享同一张表时彼此的一举一动都会互相牵制。写业务代码的人若只盯着SQL本身完全无视锁与事务的存在迟早会在一个平平无奇的周四凌晨被电话叫醒。MySQL的学习路径很长但只要你把结构和数据这条主线盘清楚把DDL的谨慎、DML的纪律养成肌肉记忆后面的索引优化、事务隔离、集群架构才有扎实的地基可打。下一篇咱接着往下走把查询那点事彻底讲透。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

C++模板元编程实战:编译期训练线性回归模型 2026/10/2 15:27:32

C++模板元编程实战:编译期训练线性回归模型

把“模板编译期机器学习”这六个字放在一起,很多人第一反应是:这怕不是两个词拼错了?模板元编程是用来搞泛型编程的,机器学习是要跑在GPU和数据流上的,怎么能在编译期完成?C模板元编程确实有一个非常硬核的…

阅读更多 →
疫情隔离管理系统全栈开发实战:SpringBoot+Vue+MyBatis设计与部署 2026/10/2 15:27:31

疫情隔离管理系统全栈开发实战:SpringBoot+Vue+MyBatis设计与部署

前阵子刚交付完一套疫情隔离管理系统,后端SpringBoot MyBatis,前端Vue Element UI,数据库用的MySQL,整个项目属于比较典型的企业级管理系统。整理源码的时候不少朋友来找我聊,说这套系统的完整源码和设计思路对他们很…

阅读更多 →
从期刊难产到顺产:Paperzz AI论文写作流水线实操 2026/10/2 15:27:31

从期刊难产到顺产:Paperzz AI论文写作流水线实操

“期刊难产”这个词,我第一次听是在组会上,导师半开玩笑地形容一位学长:文献读了一堆,实验做了一年,论文就是产不出来。后来我自己也经历了同样的周期——不是不想写,而是每次新建一个空白文档,…

阅读更多 →
Uni LLM Bench:轻量级自托管大语言模型性能基准测试工具 2026/10/2 15:27:30

Uni LLM Bench:轻量级自托管大语言模型性能基准测试工具

1. 这不是又一个“跑分网站”,而是一套能塞进你笔记本的LLM性能显微镜 Uni LLM Bench 这个名字乍看平平无奇,但拆开来看——“Uni”不是指大学,而是“统一接口”的缩写;“LLM Bench”直白点说,就是大语言模型的“体检中…

阅读更多 →
FontDiffuser:扩散模型与多尺度机制如何重塑一次性字体生成 2026/10/2 15:27:10

FontDiffuser:扩散模型与多尺度机制如何重塑一次性字体生成

AAAI2024的论文榜单里,视觉相关的方向出了不少有意思的工作,但我个人最关注的,其实是题目标题里这个FontDiffuser。为什么?因为字体生成这个任务,长期被GAN类方法统治,虽然效果越来越逼真,但细看…

阅读更多 →
慢性病数据追踪可视化:从MySQL建模到ECharts大屏实践 2026/10/2 15:27:03

慢性病数据追踪可视化:从MySQL建模到ECharts大屏实践

简介:慢性病管理数据追踪与可视化系统资源包定位为课程报告配套资料,面向需要完成健康数据分析与Web可视化项目的学生或开发者,重点解决生理指标采集、数据清洗与统计、异常预警和交互图表展示的完整实现问题。压缩包共3个文件,包…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉