MySQL 外键是什么?ON DELETE CASCADE、RESTRICT 和 SET NULL 有什么区别?
下面是一段教学模拟,不是真实面试记录。
🧑💻 面试官:外键可以帮我们解决什么问题?
🙋♂️ 我:保证关联数据存在,删父记录时可以把子记录一起删掉。
🧑💻 面试官:用户下面有一千条历史记录,也应该一起删吗?
🙋♂️ 我:不应该,要看业务规则。
🧑💻 面试官:那 CASCADE、RESTRICT、SET NULL 分别表达什么?把父记录标为 deleted,会触发 ON DELETE 吗?
外键保护「引用关系」,删除动作表达「父记录消失后怎么办」。它不替我们决定历史是否应保留,也不代替操作权限。
面试速答(60 秒版)
外键用来约束子表中的引用值,让它关联到合法的父表记录,避免出现不符合约定的孤立引用。
删除父记录时,CASCADE 会级联删除相应子记录;RESTRICT 会在仍有引用时阻止删除;SET NULL 会将子表外键字段设为空,因此字段必须允许 NULL。
在 InnoDB 中,NO ACTION 通常与 RESTRICT 一样立即检查,不能当成延迟到提交的约束。
选择时先确定数据生命周期。需要保留历史,不能随便级联删除;软删除只是修改标记,也不会触发 ON DELETE。外键保证数据关系,不负责用户授权、审计或所有业务规则。

知识点详解:父记录没了,子记录应该留下什么?
外键首先约束“指向谁”
假设 author 表保存作者,draft 表保存草稿,draft.author_id 引用 author.id。
普通字段只是一个数字,外键则要求这个数字满足引用关系。父表主键是清楚的示例,字段类型、索引和存储引擎支持也需要满足数据库要求。
子表字段如果允许 NULL,还要理解它代表“没有对应作者”,不是一条有效父表记录。MySQL 外键文档
三种删除规则,表达三种数据要求
| 规则 | 父记录删除时 | 适合表达什么 |
|---|---|---|
| CASCADE | 删除关联子记录 | 子数据没有独立保留意义 |
| RESTRICT | 有关联子记录就拒绝 | 先处理关系,再允许删除 |
| SET NULL | 保留子记录,引用字段为空 | 子数据可独立存在,允许解除关系 |
这不是优劣排名。
如果草稿必须归属于作者,可以拒绝删除或明确处理转移;如果允许匿名保留,才考虑 SET NULL;如果只是附属临时数据,也可以评估级联。
约束动作应该来自数据要求,而不是为了让一次删除接口“少写几句 SQL”。
级联删除不等于所有应用逻辑都会执行
假设应用删除草稿时,还要清除文件、更新外部索引并记录审核事件。
数据库级联删除不会自动调用我们的应用函数。MySQL 的外键级联动作也不会按普通手工删除的想象去触发所有触发器流程,应核对其明确限制。
因此,不能把需要外部清理的工作全部寄托在级联上。必须有可靠的变更处理或清理机制,并明确失败后如何补偿。
同样,级联范围可能很大,带来锁和写入负担。看起来只删除一条父记录,实际影响需要沿关系估算。
软删除与权限属于另外两层
把 author.deleted 改成 true,是 UPDATE,不是删除父记录。因此 ON DELETE 动作不会自动发生。
我们需要另外决定:子记录是否继续可见,新记录是否允许关联软删除作者,历史读取怎样处理。外键只看到父行仍然存在,不知道应用定义的“不可用”。
权限也一样。合法的外键不说明当前登录用户有权删除这条父记录。应用需要先校验身份、对象权限和操作条件,再执行数据修改。
所以外键与应用规则互相补充,不是只能二选一。
面试官继续追问
SET NULL 为什么可能建表失败?
外键字段若不允许 NULL,就与动作要求冲突。还要确认定义、类型与相关索引满足约束要求。
NO ACTION 可以让 InnoDB 到提交时再检查吗?
不能这样理解。InnoDB 不按延迟约束处理它,通常与 RESTRICT 的即时检查相同。
分库以后,还能直接靠外键保护跨库关系吗?
要看数据库的实际范围,不能假定跨独立实例仍有原来的事务和约束保证。应用需重新设计关系校验、变更和一致性处理。
面试速记卡
- 外键:保护父子引用关系,不是业务授权。
- CASCADE:父记录删除时级联删除对应子记录。
- RESTRICT:还有引用就阻止删除。
- SET NULL:保留子记录但清空引用,字段需要允许 NULL。
- 工程边界:软删除不触发 ON DELETE,外部清理与审计另行设计。
公司面试真题
这道题暂未收录可核验的公司真题来源。你可以先阅读本文解析,或浏览已收录的公司面试真题。
浏览公司面试真题 →