外键是MySQL中维护参照完整性的约束机制,要求从表字段值必须存在于主表主键或唯一键中,需InnoDB引擎、类型一致、双向索引支持,并支持CASCADE、RESTRICT等行为控制,但会降低写入性能且不适用于分库分表场景。

外键(Foreign Key)是 MySQL 中用于建立和加强两个表之间关联关系的约束机制。它本质上是一个字段(或字段组合),其值必须在另一个表的主键或唯一键中存在,从而确保“从表”里的数据不会引用“主表”中不存在的记录。
外键的核心作用是维护参照完整性
比如用户表 users(id, name) 是主表,订单表 orders(order_id, user_id) 是从表。若把 user_id 设为外键并指向 users.id,那么插入订单时,user_id 就不能填一个数据库里根本不存在的用户 ID —— 这就避免了“孤儿订单”。
这种强制校验发生在数据库层,不依赖应用程序逻辑,能从根本上防止脏数据写入。
外键生效的前提条件
不是所有表都能加外键,需同时满足:
- 两张表都必须使用 InnoDB 存储引擎(MyISAM 不支持)
- 外键列和被引用列的数据类型要严格一致(如都是 INT UNSIGNED,不能一边是 INT 一边是 VARCHAR)
- 被引用的列(通常是主表的主键)必须有索引(主键自带索引,所以一般没问题)
- 外键列本身也建议建索引(尤其在频繁 JOIN 或 DELETE 场景下,否则性能下降明显)
外键的常见行为控制(ON DELETE / ON UPDATE)
当主表记录被删或改时,外键可以定义从表如何响应:
- CASCADE:联动操作。删用户 → 自动删其所有订单;改用户 ID → 自动更新订单里的 user_id
- RESTRICT(默认):拒绝操作。只要还有订单绑着这个用户,就不允许删该用户
- SET NULL:主记录删掉后,把订单里的 user_id 设为 NULL(要求该字段允许为 NULL)
- NO ACTION:与 RESTRICT 效果基本相同,语义上更强调“由应用决定”,但 MySQL 实际执行等同于 RESTRICT
外键不是万能的,也有代价
它虽保障数据安全,但会带来额外开销:
- 每次 INSERT/UPDATE/DELETE 都要检查关联表,影响写入性能
- 涉及外键的查询常需跨表加锁,可能引发锁等待甚至死锁
- 分库分表、读写分离、微服务架构下,外键难以跨库生效,实际多由应用层兜底
- 如果仅用于数值合法性校验(比如状态码只能是 0/1/2),用 ENUM 或 CHECK 约束更轻量










