MySQL学习地图:64学时从建库到备份的实战路线
简介《MySQL数据库基础实例教程第2版》是面向软件技术、移动互联等专业学生的专业必修课教学大纲内容系统规划了MySQL数据库从入门到进阶的学习路径。大纲涵盖数据库基础知识、数据库设计、数据定义、数据操作、数据查询、数据视图、索引与分区、数据库编程及数据安全九大教学模块并配有PetStore综合实例贯穿实践环节同时说明课程从就业岗位调研入手提炼出九个典型工作任务采用项目模拟方式组织教学。课程总学时64其中讲授与实践各32学时便于教学安排与自学规划。资源包共1个PDF文件压缩包大小为341KB便于快速下载与查阅。目前已有2127人浏览学习适合高校教师用于课程设计参考也适合学生提前梳理知识框架、明确重难点作为备考或实训的纲领性材料。1. 大纲不是教程一张 64 学时的 MySQL 学习地图拿到这份《MySQL数据库基础实例教程(第2版)》教学大纲 PDF我先确认了一下它不是一本写满 SQL 示例的电子书而是一份把数据库学习切成 64 学时的课程蓝本——讲授 32 学时、课内实践 32 学时从 MySQL 安装一路排到用户权限、事务锁与日志恢复。数据库学习最容易栽在“东学一块、西学一块”这份大纲的价值恰恰在于它把知识点排成了九条任务线每个任务都挂着一个能验证的输出物比如 PetStore 库、LibraryDB 五表、能调通的存储过程。你如果正在补 MySQL 基础或者要带新人照这条线走能省掉大量试错。下面我把它拆成可执行的练习方案每个阶段标出最容易翻车的点。2. 从建库到查询把大纲前五章压实成一份可照跑的 SQL 路线大纲的前五个模块——数据库基础知识、数据库设计、数据定义、数据操作、数据查询本质上是一条完整的 SQL 主链路。很多人学 MySQL 卡住不是卡在语法难而是卡在顺序乱还没搞懂外键约束就开始写多表查询查出来的结果对不对都不知道怎么验证。这一章我按大纲的实际顺序重排成三个阶段每个阶段都配可直接抄的 SQL。2.1 设计先行先画 E-R 图再写 CREATE TABLE 才不会返工大纲第二模块把数据库设计放在数据定义前面是有意安排的。很多人上来就 CREATE TABLE后面发现外键漏了、字段冗余一堆再回头改表结构代价比想象中大得多。课程给的方法论是先做概念模型E-R 图再把实体和关系转成关系模型最后按第三范式校一遍。图书管理系统 LibraryDB 需要五张表——读者分类表、读者表、库存表、借阅表、图书表这就是一个非常典型的练习。我一般会先在纸上把实体画出来读者分类与读者是一对多读者与借阅是一对多图书与借阅是一对多库存是图书的补充信息。关系确定后再落成 SQL。以下是读者表、图书表和借阅表的建表核心写法CREATE TABLE reader_category ( category_id INT PRIMARY KEY AUTO_INCREMENT COMMENT 读者分类ID, category_name VARCHAR(50) NOT NULL UNIQUE COMMENT 分类名称UNIQUE作为替代键 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE reader ( reader_id INT PRIMARY KEY AUTO_INCREMENT, reader_name VARCHAR(30) NOT NULL, category_id INT NOT NULL, phone VARCHAR(20), -- 外键读者从属于某个分类 CONSTRAINT fk_reader_category FOREIGN KEY (category_id) REFERENCES reader_category(category_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE borrow ( borrow_id INT PRIMARY KEY AUTO_INCREMENT, reader_id INT NOT NULL, book_id INT NOT NULL, borrow_date DATE NOT NULL, return_date DATE, CHECK (return_date IS NULL OR return_date borrow_date), -- CHECK完整性约束 FOREIGN KEY (reader_id) REFERENCES reader(reader_id), FOREIGN KEY (book_id) REFERENCES book(book_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这一段把大纲第三模块的四种完整性约束都覆盖了主键约束用 PRIMARY KEY替代键用 UNIQUE参照完整性用 FOREIGN KEYCHECK 直接写在字段约束里。注意 MySQL 8.0.16 之前 CHECK 约束实际上不强制校验升级之后再依赖它才真正有效老版本里更靠谱的做法是交给应用层或者用触发器兜底。参数上外键约束的 ON DELETE 子句我没写默认是 RESTRICT即父表有子记录引用时禁止删除。想做级联删除要显式加 ON DELETE CASCADE但业务上我更推荐 RESTRICT 或 SET NULL级联删除在数据量大了以后容易误伤。字符集用 utf8mb4 而不是 utf8否则 emoji 和生僻字会存不进去排序规则对应用 utf8mb4_general_ci要求更高的场景可以用 utf8mb4_0900_ai_ci。建表完成后用 SHOW CREATE TABLE reader; 可以回看 MySQL 实际执行的 DDL这是检查建表结果最直接的方式。我每次建完表都会跑一遍这条命令确认 ENGINE 是 InnoDB、外键有没有被正确解析——很多翻车现场就是从这里开始暴露的。2.2 数据操作三板斧INSERT、UPDATE、DELETE 的边界与回滚习惯大纲第四模块把插入、修改、删除数据单独拉出来练配套要求掌握 SHOW 和 DESCRIBE 语句。数据操作本身不复杂复杂的是边界插入违反唯一约束报什么错、UPDATE 忘带 WHERE 会改掉整表、DELETE 大表的锁和日志问题。建议所有练习都放在事务里做出错就回滚这是最有用的兜底习惯。-- 插入单行 INSERT INTO reader_category (category_name) VALUES (本科生); -- 插入多行 INSERT INTO reader (reader_name, category_id, phone) VALUES (张三, 1, 13800000001), (李四, 1, 13800000002); -- 把查询结果直接灌进另一张表 INSERT INTO reader_backup (reader_id, reader_name, category_id) SELECT reader_id, reader_name, category_id FROM reader WHERE category_id 1; -- 修改务必带 WHERE UPDATE reader SET phone 13900000000 WHERE reader_id 1; -- 删除单条删和清表要分清 DELETE FROM reader WHERE reader_id 2; -- 逐行删走事务、记日志 TRUNCATE TABLE reader_backup; -- 整体清空不逐行记日志不可按行回滚先把事务包起来再操作是我在这个模块强调的习惯SET autocommit 0; 之后执行 INSERT 或 UPDATE用 SELECT 确认受影响行数没问题再 COMMIT不对就 ROLLBACK。DELETE 和 TRUNCATE 的区别要特别记牢DELETE 是 DML逐行删除、走 binlog、能配合 WHERETRUNCATE 是 DDL直接把表重置自增列也归零且不会逐行触发删除触发器。误操作后想恢复DELETE 还有后悔药TRUNCATE 基本没有。插入数据前先用 DESCRIBE reader; 看字段列表和是否允许 NULL能避免一半的字段写错问题。SHOW 语句则用来查看库表状态比如 SHOW TABLES; 列出所有表SHOW INDEX FROM reader; 查看索引这些命令在大纲里被反复要求实际工作中也确实是最常用的巡检手段。2.3 数据查询SELECT 子句执行顺序是排错的第一把尺子数据查询是大纲第五模块也是学时分配最重的一块。单表查询、多表查询、排序和分类汇总最后落到 PetStore 综合实例。SELECT 语法本身不复杂但排错时最有用的是记住各子句的执行顺序——它决定了 WHERE 里能不能用别名、HAVING 和 WHERE 有什么区别。-- 单表聚合统计每个分类下的读者数过滤掉人数少于2的分类 SELECT category_id, COUNT(*) AS reader_cnt FROM reader WHERE reader_name IS NOT NULL GROUP BY category_id HAVING reader_cnt 2 ORDER BY reader_cnt DESC LIMIT 5; -- 多表连接查出借阅记录对应的读者名和书名 SELECT r.reader_name, b.book_name, br.borrow_date FROM borrow br JOIN reader r ON br.reader_id r.reader_id JOIN book b ON br.book_id b.book_id WHERE br.return_date IS NULL ORDER BY br.borrow_date DESC;执行顺序是FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT。因为这个顺序WHERE 里不能引用 SELECT 中定义的别名 reader_cnt只能用 HAVING 过滤聚合结果ORDER BY 阶段才能用别名排序。聚合函数 COUNT、SUM、AVG、MAX、MIN 作用于 GROUP BY 分组后的数据COUNT(*) 和 COUNT(字段) 的区别在于后者不计 NULL。多表连接优先用 INNER JOIN需要左表全保留时用 LEFT JOIN。连接条件写 ON 而不是 WHERE虽然结果有时相同但 LEFT JOIN 条件下 WHERE 会把左表的空配行过滤掉语义就变了。大纲在这里还要掌握 SHOW 和 DESCRIBE 语句——实际是建议你用它们去核对表结构排查“字段名写错”“列名冲突”这类低级错误。我见过不少人在多表连接里不写表别名两个表都有 id 字段时直接报 Column id in where clause is ambiguous解决方式就是给每个表起别名并且所有字段都带前缀。3. 视图、索引与分区三个能提效但容易被误用的进阶点课程把索引与分区放在视图之后。这三个东西用好了查询效率明显提升用不好就是给自己挖坑。视图的坑在于更新限制索引的坑在于建了不用还占空间分区的坑在于类型选错查询反而变慢。我按大纲的实践要求逐个拆开讲。3.1 视图本质是存储的查询不是性能优化工具视图在大纲第六模块概念上是一张虚拟表实际上只是保存了一条 SELECT 语句。它的价值在于封装复杂查询、隐藏敏感字段、给不同角色开不同的数据口径。需要强调一句视图不会提升查询性能查询视图时底层 SQL 照样执行该全表扫描还是全表扫描。-- 创建视图只看未归还的借阅记录隐藏读者电话等敏感字段 CREATE VIEW v_borrow_overdue AS SELECT br.borrow_id, r.reader_name, b.book_name, br.borrow_date FROM borrow br JOIN reader r ON br.reader_id r.reader_id JOIN book b ON br.book_id b.book_id WHERE br.return_date IS NULL; -- 查询视图 SELECT * FROM v_borrow_overdue WHERE borrow_date 2024-01-01; -- 修改视图定义 ALTER VIEW v_borrow_overdue AS SELECT br.borrow_id, r.reader_name, b.book_name, br.borrow_date, br.return_date FROM borrow br JOIN reader r ON br.reader_id r.reader_id JOIN book b ON br.book_id b.book_id; -- 删除视图 DROP VIEW IF EXISTS v_borrow_overdue;通过视图更新数据有严格限制视图包含聚合函数、GROUP BY、DISTINCT、多表连接时不能通过视图做 INSERT 或 UPDATE。单表且包含基表主键的视图可以更新但不建议依赖它我见过因为视图更新触发基表数据被改、排查半天才发现问题来源的案例。创建视图时加 WITH CHECK OPTION 可以约束插入数据必须满足视图 WHERE 条件比如只允许插入 return_date IS NULL 的记录这样视图内数据口径不会被破坏。3.2 索引联合索引的最左前缀原则和 EXPLAIN 验证大纲索引部分要求的操作是创建和删除索引并且要看索引对查询的影响。实践中最关键的是知道什么时候建索引、建在哪些字段上。索引不是建得越多越好每个索引都要额外空间写入时还要维护 B 树写多读少的表建一堆索引是净亏。-- 普通索引 CREATE INDEX idx_borrow_date ON borrow(borrow_date); -- 唯一索引 CREATE UNIQUE INDEX uk_reader_phone ON reader(phone); -- 联合索引查询条件里同时出现 reader_id 和 borrow_date 时更合适 CREATE INDEX idx_reader_borrow_date ON borrow(reader_id, borrow_date); -- 用 ALTER TABLE 也能加索引 ALTER TABLE book ADD INDEX idx_book_name (book_name); -- 删除索引 DROP INDEX idx_borrow_date ON borrow;联合索引遵循最左前缀原则idx_reader_borrow_date 对 WHERE reader_id 1 有效对 WHERE borrow_date 2024-01-01 无效。把等值查询的字段放前面范围查询的字段放后面是联合索引设计的常见经验。加完索引后不要靠感觉判断有没有生效用 EXPLAIN 看一下执行计划EXPLAIN SELECT * FROM borrow WHERE reader_id 1 AND borrow_date 2024-01-01;关注 type 列和 key 列key 显示实际用到的索引名type 从 const、ref、range 一路到 ALL看到 ALL 基本就是全表扫描该考虑加索引了。覆盖索引是另一个优化点让查询的所有字段都包含在索引里连回表都省了。这些细节大纲没有展开但吃透索引对查询的影响是第七模块真正想让你掌握的能力。3.3 分区类型选错查询可能比不分还慢索引与分区放在同一个模块是有原因的分区是表级别的物理存储拆分索引是字段级别的加速。RANGE 分区适合按时间归档LIST 分区适合按固定枚举值拆分HASH 和 KEY 分区适合把数据均匀打散到多个分区。分区键必须包含在主键和唯一索引里这是 MySQL 的硬性规定。-- RANGE分区按年份归档借阅记录 CREATE TABLE borrow_part ( borrow_id INT NOT NULL, reader_id INT NOT NULL, borrow_date DATE NOT NULL, PRIMARY KEY (borrow_id, borrow_date) ) PARTITION BY RANGE (YEAR(borrow_date)) ( PARTITION p2022 VALUES LESS THAN (2023), PARTITION p2023 VALUES LESS THAN (2024), PARTITION p2024 VALUES LESS THAN (2025), PARTITION p_future VALUES LESS THAN MAXVALUE ); -- 查看分区情况 SELECT PARTITION_NAME, TABLE_ROWS FROM information_schema.PARTITIONS WHERE TABLE_NAME borrow_part;选错分区类型是常见问题。按时间字段做报表查询用 RANGE 分区配合分区裁剪查询条件带上时间范围时 MySQL 只扫对应分区但如果分区键建立在对查询毫无帮助的字段上每次查询都要扫描所有分区性能反而不如单表。管理分区也需要注意业务影响DROP PARTITION 会直接删掉整个分区的数据比 DELETE 快得多但也意味着不可恢复执行前必须确认这个分区确实是废弃数据。大纲要求掌握分区的创建与管理实际工作里我的建议是表数据量没到千万级、没有明确的时间归档需求之前先用索引别急着分区。4. 存储过程、触发器与事件数据库编程模块的三个易错点第八模块进入数据库编程是大纲里最像“写代码”的部分。MySQL 语言结构、存储过程、存储函数、触发器、事件五块内容难度梯度明显。存储过程是基础触发器是隐式逻辑事件是定时任务。这一章我重点说三个我实际走过弯路的地方。4.1 存储过程与函数参数模式、事务与调用方式存储过程的价值在于把一段多步骤的 SQL 逻辑封装起来减少重复代码也方便把权限按“调用过程”而不是“直接操作表”来授。大纲要求掌握创建、调用、删除以及流程控制语句。写存储过程前先改分隔符否则客户端会把分号当成语句结束这是新手最常踩的坑。-- 修改分隔符为 //避免与过程体内的分号冲突 DELIMITER // CREATE PROCEDURE sp_borrow_book( IN p_reader_id INT, IN p_book_id INT, OUT p_result VARCHAR(50) ) BEGIN DECLARE v_stock INT DEFAULT 0; SELECT stock INTO v_stock FROM book WHERE book_id p_book_id; IF v_stock 0 THEN SET p_result 无库存; ELSE INSERT INTO borrow(reader_id, book_id, borrow_date) VALUES (p_reader_id, p_book_id, CURDATE()); UPDATE book SET stock stock - 1 WHERE book_id p_book_id; SET p_result 借阅成功; END IF; END // DELIMITER ; -- 调用 CALL sp_borrow_book(1, 3, result); SELECT result;IN 参数是传入值OUT 参数是传出值INOUT 双向。过程体内 IF/ELSE、WHILE、LOOP 这些流程控制语句加上 DECLARE 声明局部变量组成了 MySQL 编程的骨架。把事务放进过程体比在外部散着写更安全整个借阅过程要么全部成功要么全部回滚不会出现库存减了但借阅记录没插进去的中间状态。存储函数和过程的区别在于函数必须有返回值可以直接用在 SELECT 里比如 SELECT cal_fine(borrow_id) FROM borrow。但函数里不能做会改变数据的事务操作规范上也不建议在函数里写 DML。这里有个经验存储过程适合封装“动作”存储函数适合封装“计算”别混用。4.2 触发器时机和粒度决定排查难度触发器是在 INSERT、UPDATE、DELETE 操作前后自动执行的 SQL。它最大的特点是隐式——你只看到一条 UPDATE背后可能还动了三张表。大纲要求掌握创建和删除综合实例里常用于日志记录或自动维护汇总字段。写法上没有太多语法难点难点在于规划触发时机和意识到它对性能的影响。DELIMITER // CREATE TRIGGER trg_reader_insert AFTER INSERT ON reader FOR EACH ROW BEGIN INSERT INTO reader_log(reader_id, action, action_time) VALUES (NEW.reader_id, INSERT, NOW()); END // DELIMITER ; -- 删触发器 DROP TRIGGER trg_reader_insert;触发器里 NEW 表示新行OLD 表示旧行UPDATE 触发器里两者都能用INSERT 只有 NEWDELETE 只有 OLD。FOR EACH ROW 表示逐行触发批量 UPDATE 一万行就执行一万次触发器这也是批量操作时触发器拖慢速度的根源。我的血泪经验是触发器里不要做复杂查询更不要调用存储过程否则排查问题时你会发现一行 UPDATE 引发的连锁反应像黑匣子一样难以追踪。4.3 事件调度器定时任务关掉等于白写事件是 MySQL 的定时任务可以用来做定期清理、定期统计、定期备份。很多人写了事件却不生效先查 event_scheduler 是否开启。大纲第八模块专门列了事件的创建与管理下面是一个每天凌晨执行归档清理的事件。-- 查看调度器状态 SHOW VARIABLES LIKE event_scheduler; -- 开启调度器重启后失效要持久化需写入配置文件 SET GLOBAL event_scheduler ON; DELIMITER // CREATE EVENT ev_clean_expired_log ON SCHEDULE EVERY 1 DAY STARTS 2024-01-01 02:00:00 DO BEGIN DELETE FROM reader_log WHERE action_time NOW() - INTERVAL 90 DAY; END // DELIMITER ; -- 事件管理 ALTER EVENT ev_clean_expired_log DISABLE; -- 临时停用 DROP EVENT IF EXISTS ev_clean_expired_log; -- 删除ON SCHEDULE EVERY 1 DAY 是频率STARTS 指定首次执行时间。事件的权限要求比较明确创建事件需要 EVENT 权限操作的是 mysql.event 表。此外事件里的 SQL 默认不受事务保护DELETE 这类操作要谨慎最好也带上 LIMIT 分批删。触发器和事件的区别一句话说清触发器由 DML 触发事件由时间触发二者都不是能随意堆砌的东西都会让数据库的行为变得不透明。5. 数据安全与备份恢复权限、事务、日志的五类常见问题排查最后这个模块是事故高发区。用户权限、备份恢复、事务与多用户每块都有典型的翻车现场。我挑了五类实际工作中反复出现的问题按现象、原因、解决三步说透。很多事故发生后才发现数据库的后悔药其实早就准备好了只是你没来得及吃。5.1 用户与权限最小授权和 GRANT 不生效权限管理的目标不是功能多而是权限小。大纲要求掌握用户增删、授权收权和界面操作。命令行方式如下-- 创建用户并设置密码 CREATE USER app_userlocalhost IDENTIFIED BY StrongPass_2024; -- 只授查询权限 GRANT SELECT ON LibraryDB.* TO app_userlocalhost; -- 授予增删改权限 GRANT SELECT, INSERT, UPDATE, DELETE ON LibraryDB.* TO app_userlocalhost; -- 授权存储过程执行权 GRANT EXECUTE ON PROCEDURE LibraryDB.sp_borrow_book TO app_userlocalhost; -- 回收权限 REVOKE DELETE ON LibraryDB.* FROM app_userlocalhost; -- 删除用户 DROP USER app_userlocalhost;现象一执行 GRANT 后客户端连进来仍然报权限不足。原因如果之前直接用 INSERT/UPDATE 改过 mysql.user 表需要刷新权限或者是关联了新库新表但没加 FLUSH PRIVILEGES。解决统一用 GRANT/REVOKE 语句操作不要手动改权限表改完后执行 FLUSH PRIVILEGES。MySQL 8.0 里默认认证插件 caching_sha2_password 导致老客户端连接报错也很常见解决方式是升级客户端或创建用户时显式指定 mysql_native_password。5.2 备份与恢复mysqldump 参数与 binlog 增量备份是大纲第九模块的重头戏要求掌握备份与恢复的各种方法。逻辑备份最常用的是 mysqldump物理备份用 xtrabackup 的场景也有但课程范围里 mysqldump 足够。我常用的一组参数如下# 单库逻辑备份尽量少锁表 mysqldump -uroot -p --single-transaction --set-gtid-purgedOFF --default-character-setutf8mb4 LibraryDB LibraryDB_$(date %F).sql # 恢复先建库再导入 mysql -uroot -p -e CREATE DATABASE IF NOT EXISTS LibraryDB DEFAULT CHARSET utf8mb4; mysql -uroot -p LibraryDB LibraryDB_2024-06-01.sql--single-transaction 在 InnoDB 下用一致性快照备份备份期间 DML 不影响一致性但 DDL 仍可能造成问题--set-gtid-purgedOFF 是为了让备份文件能恢复到非 GTID 或目标差异较大的实例--default-character-setutf8mb4 防止中文乱码。恢复前先建库再导入顺序反了会直接报 No database selected。现象二备份恢复后某张表的自增列又从头开始产生主键冲突或业务错乱。原因mysqldump 默认导出表结构和数据但不重置 AUTO_INCREMENT 计数器恢复到新库后计数器按现有数据重新计算如果之前删过大量行新插入的记录可能复用旧 ID。解决恢复后对关键表执行 ALTER TABLE xxx AUTO_INCREMENT N; 或者应用层不依赖自增 ID 的连续性。需要补充的是只有全量备份、没有 binlog 时误删数据后最多只能恢复到上一次备份点。想恢复到误删前一刻必须开启 binlog 并配合增量导入-- 查看 binlog 状态 SHOW VARIABLES LIKE log_bin; SHOW BINARY LOGS; -- 导出指定时间段的 binlog 为 SQL mysqlbinlog --start-datetime2024-06-01 00:00:00 --stop-datetime2024-06-01 12:00:00 binlog.000023 inc_20240601.sqlmysqlbinlog 导出的文件同样用 mysql 客户端导入。binlog 是数据库同步、主从复制的核心依赖开启它会让写入有额外开销但相比误删后没有后悔药可用这笔开销很值得。5.3 事务与多用户元数据锁、锁等待与外键失败的排查事务的 ACID 特性和多用户并发下的锁定机制是大纲第九模块的收尾内容。理论部分不多说直接给三个高频事故的排查思路。现象三执行 ALTER TABLE 修改表结构时一直卡在 Waiting for table metadata lock。原因有长事务或者未提交的查询还握着这张表的元数据锁。解决先查 information_schema.innodb_trx 找到事务 ID再 kill 对应连接。-- 查未结束的事务 SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id FROM information_schema.innodb_trx; -- 找到线程ID后结束该会话 KILL 12345;现象四UPDATE 语句执行缓慢且大量会话阻塞在同一个状态。原因更新条件没走索引InnoDB 从行锁升级为大量行锁甚至间隙锁互相等待形成锁链。解决先杀掉阻塞源再用 EXPLAIN 检查 UPDATE 的 WHERE 是否走索引最后重试并控制事务里更新的行数。现象五删除借阅记录时提示 Cannot delete or update a parent row: a foreign key constraint fails。原因子表里还有引用这条父表记录的数据。解决先删子表记录或者把外键改成 ON DELETE CASCADE但后者要确认业务允许级联删除。这个错误在课程实验里几乎人手一次看到外键约束失败的报错第一步永远是查子表数据而不是去看父表。事务这里有个习惯建议把事务做得短而明确BEGIN 后尽快提交不要在事务里做查询后停下来等用户确认。长事务是锁等待和 binlog 膨胀的温床也是各类诡异死锁的源头。大纲要求“了解事务和多用户处理机制”实际上这块内容决定了你在生产环境里能不能活过大促和并发高峰。6. 把大纲转成两周训练闭环一张自查清单和三个验证手段大纲的价值在拆解拆完之后怎么确认自己真的学会了我会用三个手段做体检。第一个手段是查 information_schema把每个表的数据量和空间占用拉出来确认建表、数据操作后的现状符合预期SELECT table_name, table_rows, ROUND(data_length / 1024 / 1024, 2) AS data_mb, ROUND(index_length / 1024 / 1024, 2) AS index_mb FROM information_schema.tables WHERE table_schema LibraryDB ORDER BY data_mb DESC;如果在练习中给表加过索引index_mb 会上升这能直观看到索引的空间成本。第二个手段是 EXPLAIN 每一条你写的核心查询确认 key 列有索引用、type 不是 ALL。第三个手段是把大纲的九个模块压缩成两周计划第 1-2 天安装与建库建表第 3-4 天数据操作与单表查询第 5-6 天多表查询与视图第 7-8 天索引和 EXPLAIN 调优第 9-10 天存储过程与触发器第 11 天事件与定时清理第 12 天备份恢复演练第 13-14 天事务与权限的多人协作测试。每一阶段完成就把 PetStore 实例对应的代码敲一遍别只读。模块验证方法安装配置Navicat 能连上本地 MySQL命令行也能连接数据库设计E-R 图能转成关系模型范式检查无冗余数据定义SHOW CREATE TABLE 输出与设计一致数据操作事务内增删改后 ROLLBACK/COMMIT 可控数据查询每类查询跑通并 EXPLAIN 验证过视图能建能查知道哪些视图不可更新索引分区key 列有值分区裁剪生效数据库编程存储过程带 IN/OUT 参数跑通事件能触发数据安全低权限用户只能访问授权库表我带新人时吃过最大的亏是重讲解轻验证讲完一大轮一上机就在外键约束和权限上报错后来强制每个模块收尾必须过一遍自查清单翻车率立刻降下来。从那以后我每次带人学 MySQL都会先把这份大纲的学时分配合并成计划表再让他逐项打钩。课程大纲是别人的骨架能不能变成你自己的肌肉取决于每一步你有没有真的跑过。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

SAP MM采购申请与计划协议:从PR到交货计划行的全流程解析

SAP MM采购申请与计划协议:从PR到交货计划行的全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 17:23:22 阅读更多 →
PCIe协议分析仪实战:用Summit T3-8破解链路训练与TLP调试难题

PCIe协议分析仪实战:用Summit T3-8破解链路训练与TLP调试难题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 17:23:22 阅读更多 →
智慧油气物联云平台搭建与落地:边缘计算、数据存储全解析

智慧油气物联云平台搭建与落地:边缘计算、数据存储全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 17:23:22 阅读更多 →

最新新闻

JavaWeb入门实战:从IDEA配置到Tomcat部署Servlet项目全指南

JavaWeb入门实战:从IDEA配置到Tomcat部署Servlet项目全指南

很多学完 Java SE 的朋友,一进入 JavaWeb 就卡住了。教材翻了几页,视频刷了几个,代码也照着敲了,结果项目一运行就报错:404、端口被占、lib 目录空、访问不到 Controller……这些场景我当年全都经历过。说实话&#xf…

2026/10/3 18:02:44 阅读更多 →
Redis与MySQL数据一致性:从Cache Aside到Binlog订阅的可靠方案

Redis与MySQL数据一致性:从Cache Aside到Binlog订阅的可靠方案

1. 面试官问出这道题时,到底在想什么? 后端开发干到一定年头,基本都会被这道题堵在面上:“Redis 和 MySQL 的数据一致性怎么保证?” 我很少听到有人能一次答得干净利落,大多数时候是“先删缓存,…

2026/10/3 18:02:44 阅读更多 →
Ubuntu键盘失效排查攻略:从驱动冲突到输入法修复

Ubuntu键盘失效排查攻略:从驱动冲突到输入法修复

别急着重装系统:Ubuntu 26 键盘突然失效的完整排查与修复 先说说我遇到的情况:某天给一台装了 Ubuntu 26.04 的台式机换了块 NVMe 硬盘,系统倒是正常引导,进到桌面后鼠标还能动,但键盘怎么敲都没反应——内置键盘、USB…

2026/10/3 18:02:44 阅读更多 →
OpenClaw安装实战:基于WSL2的本地AI Agent与Obsidian联动

OpenClaw安装实战:基于WSL2的本地AI Agent与Obsidian联动

最近AI agent圈子热度很高,OpenClaw这个开源项目——也就是大家常说的"AI龙虾"——被越来越多的人提起。如果你刷到过"Clawdbot"这个名字,它俩其实是同一个东西,2025年项目更名成了OpenClaw,视觉形象是一只卡…

2026/10/3 18:02:44 阅读更多 →
低成本ArduPilot无人车:APM飞控+有刷电调航点导航实战

低成本ArduPilot无人车:APM飞控+有刷电调航点导航实战

折腾了个把月的ArduPilot无人车,终于能在楼下按航点自己跑一圈了。整个过程花得不多——一块一百多块的APM飞控、两个几十块的双向有刷电调、一辆二手玩具车底盘改出来的架子,加起来比一套Pixhawk加无刷动力便宜一大截。如果你也是学生党、创客&#xff…

2026/10/3 18:02:43 阅读更多 →
Java共享台球室无人系统与微信双端联动设计实战拆解

Java共享台球室无人系统与微信双端联动设计实战拆解

项目拆解:Java共享台球室的无人系统与微信双端联动做共享项目的朋友应该都有感触,最近两年共享台球室、共享茶室、共享棋牌室这类“无人值守业态”突然多了起来。我一个做实体门店系统的朋友去年底接了个需求,要给本地几家台球厅做一套“顾客…

2026/10/3 18:01:43 阅读更多 →

日新闻

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南 【免费下载链接】ex-skill 前任 skill 项目地址: https://gitcode.com/gh_mirrors/exsk/ex-skill 前任.skill 是一个运行在 Claude Code 上的开源 Skill:导入微信、iMessage、短信、…

2026/10/3 0:00:27 阅读更多 →
45个经典Linux面试题:从命令到网络排障的完整考点解析

45个经典Linux面试题:从命令到网络排障的完整考点解析

刚开始带应届生的时候,我最头疼的就是他们拿着一摞Linux面试题背得滚瓜烂熟,一上机全露馅。后来自己从被面的人变成面别人的人,才慢慢摸清楚:Linux面试题考的根本不是答案本身,而是你面对一个不确定的系统问题时&#…

2026/10/3 0:01:28 阅读更多 →
SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

简介:本资源是一份面向SAP ABAP开发人员、生产计划专员及ERP实施顾问的实操型操作指南,聚焦SAP生产预留核心业务场景,系统解决物料预留创建、查询、校验与批量处理等高频问题。文档以结构化方式覆盖预留背景原理、OMC2编码规则、工厂级参数配…

2026/10/3 0:01:28 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/3 9:14:33 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/3 9:47:50 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/3 9:42:31 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:35 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:36 阅读更多 →