简介面向互联网岗位笔试备考的MySQL基础理论试题集以PDF文件形式整理了选择题、填空题、简答题与设计题四大题型内容覆盖数据库系统核心概念、SQL数据定义与操纵功能、事务ACID特性、数据完整性、视图、存储过程、触发器及并发控制等高频考点。压缩包内仅1个PDF文档约252KB轻量易下载适合数据库笔试前快速自测与查漏补缺。已有570人学习下载。题解部分逐题点明关键结论如数据库系统核心为DBMS、SELECT是使用最频繁的操纵语句、数据冗余导致数据不一致简答题则系统归纳建表改表删表语句、存储过程四大优点、常见约束类型及事务提交与回滚的区别并附学生选课场景的SQL查询设计题有助于读者从原理到实践强化理解。整体采用题目加答案对照编排便于快速检验MySQL知识掌握程度。1. 这份 MySQL 笔试题一值得换一个晚上刷完再睡马上要笔试却在“数据库系统的核心是什么”这种送分题上卡住说明一个问题平时写 CRUD 很顺但底层理论不成体系。这份《mysql数据库笔试题一》不是刷题模板它把数据库系统核心、SQL 功能、事务、约束、存储过程、触发器以及三道经典多表查询设计题收在一份卷子里恰好是开发岗笔试最高频覆盖的知识面。适合三类人准备笔试的应届生、刚转行需要补理论基础的初级工程师以及想快速自测 MySQL 基础掌握程度的老开发。下面按这套题的考查顺序把每个考点拆开讲透。2. 数据库核心概念DBMS 为什么是核心事务和故障怎么考2.1 数据库系统的核心数据模型 vs 数据库管理系统选择题第一题问“数据库系统的核心是什么”选项给了数据库、数据库管理系统、数据模型、软件工具标准答案是数据库管理系统DBMS。先说结论数据库本身只是一堆存储在磁盘上的文件集合真正让这些文件变成“可查询、可控制、可恢复”的系统是 DBMS。DBMS 负责解析 SQL、管理存储、控制并发、做权限校验、生成日志并参与故障恢复——这些是笔试常考的几个功能维度。数据模型关系模型、层次模型、网状模型描述的是数据组织和表达规则它是一种理论抽象不是运行时的管理系统所以选“数据库管理系统”而不是“数据模型”。如果笔试里再出现类似题记住一条判断线问“系统的核心”指的是运行时要靠它调度一切的组件问“数据结构的基础”才往“数据模型”上靠。实际开发中你接触的 MySQL 服务端进程就是那个 DBMS你写的建表语句和查询语句都是在跟它对话。2.2 SQL 语言三大功能数据定义、数据操纵、数据控制第二题SQL 语言具有的功能正确选项是数据定义、数据操纵、数据控制。数据定义语言DDL对表结构做操作CREATE、ALTER、DROP。数据操纵语言DML对数据做操作SELECT、INSERT、UPDATE、DELETE。数据控制语言DCL管权限GRANT、REVOKE。很多初学者会把“关系规范化”也当成 SQL 的功能错就错在这里——规范化是设计阶段的产物是数据库设计师做的事不是 SQL 语言本身的能力。第三题问四个 DML 语句里最常用的是哪一个答案是 SELECT。这句话看起来像废话实际逻辑是SELECT 是唯一不修改数据但能完成检索、统计、联表、分组等复杂语义的语句INSERT、UPDATE、DELETE 都是写入型操作设计场景远没有 SELECT 多。笔试考到这道题时干脆答 SELECT它也是后续设计题的基础。2.3 事务的原子性、一致性与 COMMIT/ROLLBACK 的实际含义第九、十题连着考事务。第九题问事务执行成功则全部更新提交失败则已做的更新恢复原状保持数据库处于什么状态——答案是一致性。第十题问并发操作不加以控制会带来什么问题——答案是不一致。事务的原子性不是说“每一步都成功”而是说“要么全部生效要么全部不生效”一致性是说事务执行前后数据库都处于合法状态约束没有被破坏。这两条经常被混着考原子性关注“操作粒度”一致性关注“数据状态”。第七题考 CREATE答案用 CREATE TABLE 创建关系表第八题问保证授权用户对数据库的修改不会造成一致性损失答案是完整性——完整性约束主键、外键、CHECK会拒绝破坏数据语义的写入和并发控制里的锁是两回事题里用“授权用户”做干扰项实际考的是约束机制。在 MySQL 里演示提交与回滚最直接的方式是用一个显式事务START TRANSACTION; UPDATE account SET balance balance - 100 WHERE user_id 1; UPDATE account SET balance balance 100 WHERE user_id 2; -- 如果两个更新都成功执行提交让结果落盘 COMMIT; -- 如果第二条更新报错执行回滚恢复到事务开始前的状态 ROLLBACK;逻辑说明START TRANSACTION 开启一个新事务两条 UPDATE 是同一个逻辑动作的两个半场任何一步失败另一步都必须撤销COMMIT 把所有变更写回物理文件并释放事务占用的锁ROLLBACK 放弃本事务内所有未提交的变更。参数与使用注意MySQL 默认开启自动提交autocommit1单条语句会自动提交写多语句事务时显式加 START TRANSACTION 才有意义如果中途语句报错但事务没有显式 ROLLBACK事务仍可能处于未决状态锁不会被释放运维上常见“更新没生效但表被锁住”的现象。2.4 数据库运行中的三类故障事务故障、系统崩溃、磁盘故障填空题第二题给了三个空Transaction failure、System crash、Disk failure。中文语境下通常翻译为事务故障、系统故障、介质磁盘故障。故障类型典型场景恢复策略事务故障Transaction failure事务内部逻辑错误、死锁被选为牺牲品回滚该事务日志中 Undo系统崩溃System crash断电、操作系统重启、内存数据丢失重启后根据日志重做未落盘事务Redo磁盘故障Disk failure磁盘物理损坏、数据文件丢失通过备份和归档日志恢复这三种故障和答案的顺序是绑定的笔试填空常见原题。理解层面要知道事务故障只需要撤销当前事务系统崩溃需要重做磁盘故障需要从备份恢复后再重做恢复成本依次递增。后面避坑章节里关于“回滚不生效”的问题根源也在系统崩溃与事务故障的恢复机制差异上。3. 表与约束实战CREATE、ALTER、DROP 和五种约束的用法3.1 建表、改表、删表的三句话简答题第一题如何创建表、修改表、删除表。答案本身很简单但笔试要求你能区分 DDL 和 DML并把 ALTER 的常见子句答全。-- 创建表定义字段名、类型、约束条件 CREATE TABLE student ( sno INT PRIMARY KEY, sname VARCHAR(50) NOT NULL, sex CHAR(2), age INT, department VARCHAR(100) ); -- 修改表新增字段、修改字段类型、删除字段 ALTER TABLE student ADD COLUMN phone VARCHAR(20); ALTER TABLE student MODIFY COLUMN sex VARCHAR(4); ALTER TABLE student DROP COLUMN phone; -- 删除表连同表结构和数据一起删除 DROP TABLE IF EXISTS student;逻辑说明CREATE TABLE 定义列和约束是唯一能一次性把结构建完整的方式ALTER TABLE 支持 ADD COLUMN 加字段、MODIFY COLUMN 改类型、CHANGE COLUMN 改字段名、DROP COLUMN 删字段DROP TABLE 直接删除结构IF EXISTS 参数可以避免表不存在时报错。参数说明VARCHAR(50) 里的长度表示最大字符数不是字节数NOT NULL 表示该列不允许空值DROP 是危险操作生产环境不要用 DROP TABLE 清理数据用 TRUNCATE 或 DELETE 更安全因为 DROP 会连表定义一起销毁后悔药很难找。实际使用中我习惯先把 CREATE 语句保存在建表脚本里改结构时用 ALTER 生成增量脚本避免直接在测试库上手改改乱了拿不到原始 DDL。面试官如果追问“ALTER 修改字段名怎么写”答案是ALTER TABLE student CHANGE COLUMN sex gender VARCHAR(4)CHANGE 和 MODIFY 的区别就在字段名能不能改。3.2 五种约束在笔试和建表里的真实分工简答题第四题考的约束五种主键约束、唯一约束、外键约束、检查约束、默认约束。约束类型英文关键字完整性类型关键规则主键PRIMARY KEY实体完整性一个表只能有一个主键可含多个字段字段不能为 NULL唯一UNIQUE实体完整性一个表可以有多个可含多个字段允许空值MySQL 中多个 NULL 不冲突外键FOREIGN KEY引用完整性外键字段的值必须存在于被引用表的主键中检查CHECK域完整性字段值必须满足表达式默认DEFAULT域完整性不写该字段时用默认值一个字段只能有一个默认值笔试最容易考的两个区别主键和唯一约束的区别——主键有且仅有一个且隐式建立索引唯一约束可以有多个它是“允许为空但重复值不行”。外键和检查约束的区别——外键管表与表之间的引用关系检查约束管单表内字段取值的合法性。填空题第一题还考了数据冗余的两个问题浪费存储空间及修改麻烦、潜在的数据不一致性这个点后面避坑章节会展开。3.3 把约束写进建表语句的完整示例设计题里的表结构其实漏了约束笔试真题要求学生手写 SQL实际生产建表通常把约束写全。CREATE TABLE course ( id INT PRIMARY KEY AUTO_INCREMENT, cno VARCHAR(10) NOT NULL, cname VARCHAR(100) NOT NULL ); CREATE TABLE student ( sno VARCHAR(12) PRIMARY KEY, sname VARCHAR(50) NOT NULL, age INT CHECK (age 0 AND age 200), department VARCHAR(100) ); CREATE TABLE sc ( sno VARCHAR(12), cno VARCHAR(10), score DECIMAL(5,2), PRIMARY KEY (sno, cno), FOREIGN KEY (sno) REFERENCES student(sno), FOREIGN KEY (cno) REFERENCES course(cno) );逻辑说明sc 表用复合主键sno, cno保证一个学生一门课只有一条成绩记录外键把选课记录和两个主表连起来CHECK 约束限制年龄在合法范围内。参数说明AUTO_INCREMENT 用于自增主键DECIMAL(5,2) 表示最多 5 位数字、其中 2 位是小数适合成绩这种需要精度的字段。这里有两个实际开发里容易被忽略的坑。第一MySQL 5.7 及更早版本默认引擎 InnoDB 对 CHECK 约束是“语法接受、行为忽略”从 8.0.16 起才真正强制执行如果你在 5.7 里靠 CHECK 挡非法数据是挡不住的数据照样进去。第二外键在 MySQL 里要求两个表引擎都是 InnoDB 才会生效MyISAM 不认外键混用引擎时外键定义不报错但引用完整性不会被校验。4. 存储过程与触发器笔试题背后对应的工作场景4.1 存储过程的四个优点背下来也要能说透简答题第二题存储过程的优点标准答案是四句话提高性能、减轻网络拥塞、一致性较好、改善安全机制。笔答时四个点要和原理对应起来不能只写词。一个简单的存储过程示例DELIMITER $$ CREATE PROCEDURE get_student_by_course(IN course_name VARCHAR(100)) BEGIN SELECT s.sno, s.sname FROM student s JOIN sc ON s.sno sc.sno JOIN course c ON sc.cno c.cno WHERE c.cname course_name; END$$ DELIMITER ;逻辑说明这个存储过程接收一个课程名参数内部执行多表联查返回选修该课程的学生学号和姓名DELIMITER $$ 是为了让 MySQL 客户端把整个 BEGIN...END 块当作一条语句提交结束时改回分号。参数说明IN 表示输入参数调用时用CALL get_student_by_course(计算机原理)。如果要做输出参数把 IN 换成 OUT既做输入又做输出就用 INOUT。四个优点展开说提高性能存储过程预编译第一次执行后 SQL 不需要每次重新解析减少编译开销多个操作在数据库进程内完成省去客户端和服务器之间的多次往返。减轻网络拥塞把整段业务逻辑封装成一次 CALL而不是发 10 条 SQL网络包数量大幅下降批量导入、复杂报表这类场景收益最明显。一致性较好相同逻辑集中在一处不同客户端调用的是同一段代码不会出现 A 客户端写的逻辑和 B 客户端不一致的情况。改善安全机制可以只给应用层授予执行存储过程的权限而不授予直接访问底层表的权限把敏感表结构和数据隔离在存储过程后面。笔试里经常跟一句“存储过程和函数的区别”函数必须有返回值、常被用在 SELECT 表达式里存储过程不需要返回值、常被独立 CALL。4.2 触发器的类型、触发时机与使用边界简答题第三题触发器是什么有哪几种有什么优点。答案触发器是 T-SQL 语句集组成的代码块在响应某些动作时自动激活类型有 INSERT、DELETE、UPDATE 三种优点是防止不正确、未授权、不一致的改变。在 MySQL 里触发器挂在具体表上DML 语句命中时自动执行CREATE TRIGGER trg_sc_after_insert AFTER INSERT ON sc FOR EACH ROW BEGIN -- 同步选课数量向统计表累加该学生的选课数 UPDATE student_course_count SET course_num course_num 1 WHERE sno NEW.sno; END;逻辑说明AFTER INSERT 表示插入成功之后触发FOR EACH ROW 表示每一行插入都执行一次NEW 关键字引用新插入的行这里取 NEW.sno 作为统计表的更新条件。参数说明MySQL 触发器有 BEFORE 和 AFTER 两个时机加上 INSERT、UPDATE、DELETE 三种事件组合成六种写法OLD 引用变更前的行NEW 引用变更后的行UPDATE 里两者都能用。触发器体内不允许显式开启事务也不建议在里面写复杂查询触发器执行时间过长会拖慢每一次 DML。触发器的优点在笔试答案里很明确但它也有明显的使用边界触发器的行为是隐式的应用层很难从代码里看出“插入一条记录还会同步更新统计表”排查问题时要翻表结构里的触发器列表高并发写入时触发器会放大锁的持有时间容易把简单 INSERT 的响应时间拉长。我一般在合规审计、数据同步这类固定动作上用触发器业务规则尽量放在存储过程或服务层。5. 避坑实录数据冗余、并发不一致和视图的五个翻车点第十题说并发操作不加以控制会带来数据不一致第六题说数据不一致的根本原因是数据冗余。这些是考点但真实的坑比答案更细下面几条都是我见过或踩过的。5.1 数据冗余不只是多占空间的问题现象把学生的部门名称冗余到选课表里部门改名后报表里同时出现新名字和旧名字数据对不上。原因填空第一题的答案已经点破——数据冗余会导致浪费存储空间和修改麻烦潜在的数据不一致性。同一份信息存了多份更新时漏改其中一份数据就从“冗余”变成了“矛盾”。解决按设计题给出的三表结构来拆把部门信息收归 student 表sc 表只存学号、课程编号、成绩改名只改一处查询用 JOIN 关联。原则是冗余存储不一定错但冗余的字段必须由同一事务和同一代码路径维护否则就要拆表。5.2 并发操作不控制丢失更新是怎么发生的现象两个会话同时读同一行各改一个字段后先后写回先写的那次被后写完全覆盖数据丢了。原因没有锁或隔离级别太低事务之间互相无感知这是选择题第十题说的并发问题具体形态通常表现为丢失更新、脏读、不可重复读和幻读。解决给关键写操作加显式锁。一种常见做法是对要更新的行先执行SELECT ... FOR UPDATE锁住当前行再更新另一种是从业务上让所有更新走同一存储过程把并发串行化。如果隔离级别是 READ COMMITTED还要预留“更新后又读到旧值”的警觉必要时把隔离级别提到 REPEATABLE READ。5.3 把视图当成物理表用的翻车现场现象视图查出来的数据慢得离谱以为往视图里建了索引就能加速结果索引建不上去。原因视图是虚表填空题第三题的原话——视图是从一个或几个基本表中导出的表数据库只存放视图的定义不存放视图对应的数据。视图每次查询都实时执行定义里的 SELECT它没有物理文件自然没有自己的索引。解决把视图当作“封装好的查询语句”来用优化入口是优化视图内部那个 SELECT 的执行计划必要时对底层基本表建索引。如果对性能要求苛刻就用物化表定期刷新汇总数据代替视图而不是纠结“给视图加索引”。5.4 事务回滚了数据却没变回去现象在一个事务里执行两条 UPDATE第一条成功后第二条报错程序没处理错误直接断开了连接再查数据发现第一条已经变了且表一直处于锁状态。原因两条 UPDATE 的第一条执行成功后处于未提交状态第二条失败时如果没有显式 ROLLBACK事务没有正常结束连接断开后事务状态取决于连接处理策略如果 autocommit 开启第一条语句其实已经单独提交第二条失败本来就带不回第一条两者根本不在同一个事务里。解决显式开启事务把 COMMIT 和 ROLLBACK 都写在代码里通过 try-catch 保证失败路径一定走 ROLLBACK执行前先查SELECT autocommit;确认多语句事务处于受控状态。验证方法也很直接回滚后立刻 SELECT 原行确认数值回到事务开始前的值。5.5 死锁不是数据库 bug是资源竞争现象两个事务各自锁住一张表的一行然后互相等对方释放锁数据库检测到死锁后回滚其中一个事务应用报 Deadlock found。原因并发更新的资源顺序不一致。事务 A 先更新 student 再更新 sc事务 B 先更新 sc 再更新 student两个事务在等待对方完成时互相卡死。解决统一所有事务的资源访问顺序比如都“先 student 后 sc”把大事务拆小缩短锁持有时间死锁发生时系统会自动牺牲代价较小的事务应用层捕获死锁错误后重试即可。死锁本身不代表代码错误但同一个位置频繁出现死锁通常就是访问顺序问题。6. 把三道设计题吃透子查询、分组统计与连接的取舍设计题给了三张表Student学号、姓名、性别、年龄、组织部门、Course编号、课程名称、Sc学号、课程编号、成绩。三道题覆盖了笔试里最高频的三种写法三层子查询、反向子查询、分组统计。6.1 题目一查选修“计算机原理”的学生学号和姓名标准答案是三层子查询先查课程编号再通过 sc 表找到学号集合最后回 student 表取姓名。等价写法用 JOIN 更直白SELECT DISTINCT s.sno, s.sname FROM student s JOIN sc ON s.sno sc.sno JOIN course c ON sc.cno c.cno WHERE c.cname 计算机原理;逻辑说明先过滤课程名再通过选课表关联学生表取学号和姓名。参数说明DISTINCT 用于去重防止同一个学生因多条选课记录被查出重复行考场上不会判错。6.2 题目二查“周星驰”同学选修的课程名称反向子查询先从 student 拿学号再从 sc 拿课程编号集合最后从 course 取课程名。JOIN 写法同样成立SELECT c.cname FROM course c JOIN sc ON c.cno sc.cno JOIN student s ON sc.sno s.sno WHERE s.sname 周星驰;这类“按名字查关联数据”的题关键是不可把学生名直接和课程表关联必须经过选课表作为中间桥梁否则会产生笛卡尔积。6.3 题目三查选修了 5 门课程的学生学号和姓名标准答案用 GROUP BY HAVINGSELECT sc.sno, s.sname FROM sc JOIN student s ON sc.sno s.sno GROUP BY sc.sno, s.sname HAVING COUNT(sc.cno) 5;这里最容易踩的坑是条件的过滤对象是“每个学生选课条数”必须用 HAVING 而不是 WHERE。参数说明WHERE 在分组前执行只能过滤原始行COUNT 是在分组之后才计算出来的所以过滤分组结果的条件必须放在 HAVING 里。另一个细节是分组字段要带上 sname避免只按 sno 分组导致姓名取不到。6.4 连接写法和子查询的取舍子查询和 JOIN 的答案在笔试里都算对但实际开发中表数据量上来后相关子查询的性能往往不如 JOIN。我现在的习惯是先写 JOIN 版本跑通逻辑再用 EXPLAIN 看执行计划如果优化器把 JOIN 转成了临时表或嵌套循环再考虑拆成两步查询或加索引。从那以后我每次做这类查询都强制先看一遍执行计划再决定要不要换成子查询这个习惯帮我避开过好几次生产环境上的查询超时。希望帮到你。本文还有配套的精品资源点击获取