【禁用外键】为什么互联网大厂禁用外键约束?详谈外键的优缺点和使用场景

简介: 从多个层面分析数据库外键的优缺点,并给出外键的使用场景和禁止使用的场景。

 导航:

【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析

目录

一、外键介绍

1.1 概述

1.2 练习

1.2.1 数据准备

1.2.2 验证有外键时,删除记录要维护外键

1.2.3 重新添加外键

1.2.4 查询所有外键

二、外键的优缺点

2.1 外键缺点

2.2 外键优点

三、适用场景

3.1 哪些情况下不要用外键?为什么互联网大厂禁用外键约束?

3.2 哪些情况下可以用外键?


一、外键介绍

1.1 概述

-- 创建表时添加外键约束
CREATE TABLE 表名(
   列名 数据类型,
   [CONSTRAINT] [外键取名名称] FOREIGN KEY(外键列名) REFERENCES 主表(主表列名) 
); 
-- 创建表时添加外键约束,constraint译作限制,束缚;references译作关联,参考,提及
create table 表名(
   列名 数据类型,
   [constraint] [外键取名名称] foreign key(外键列名) references 主表(主表列名) 
);

image.gif

-- 建完表后添加外键约束
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);
-- 建完表后添加外键约束
alter table 表名 add constraint 外键名称 foreign key (外键字段名称) references 主表名称(主表列名称);

image.gif

  • 删除外键约束
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;

image.gif

1.2 练习

1.2.1 数据准备

image.gif

-- 删除表
DROP TABLE IF EXISTS emp;
DROP TABLE IF EXISTS dept;
-- 部门表
CREATE TABLE dept(
  id int primary key auto_increment,
  dep_name varchar(20),
  addr varchar(20)
);
-- 员工表 
CREATE TABLE emp(
  id int primary key auto_increment,
  name varchar(20),
  age int,
  dep_id int,
  -- 添加外键 dep_id,关联 dept 表的id主键
  CONSTRAINT fk_emp_dept FOREIGN KEY(dep_id) REFERENCES dept(id)  
);

image.gif

添加数据

-- 添加 2 个部门
insert into dept(dep_name,addr) values
('研发部','广州'),('销售部', '深圳');
-- 添加员工,dep_id 表示员工所在的部门
INSERT INTO emp (name, age, dep_id) VALUES 
('张三', 20, 1),
('李四', 20, 1),
('王五', 20, 1),
('赵六', 20, 2),
('孙七', 22, 2),
('周八', 18, 2);

image.gif

image.gif

image.gif

1.2.2 验证有外键时,删除记录要维护外键

此时删除 研发部 这条数据,会发现无法删除。

DELETE FROM dept WHERE id=1

image.gif

image.gif

1.2.3 验证没外键时,删除记录无需维护外键

删除外键

alter table emp drop FOREIGN key fk_emp_dept;

image.gif

此时删除 研发部 这条数据,会发现删除成功:

DELETE FROM dept WHERE id=1

image.gif

image.gif

image.gif

image.gif

1.2.3 重新添加外键

alter table emp add CONSTRAINT fk_emp_dept FOREIGN key(dep_id) REFERENCES dept(id);

image.gif

1.2.4 查询所有外键

SELECT 
  COLUMN_NAME, 
  CONSTRAINT_NAME, 
  REFERENCED_TABLE_NAME, 
  REFERENCED_COLUMN_NAME 
FROM 
  INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
WHERE 
  TABLE_NAME = 'emp' 
  AND REFERENCED_TABLE_NAME IS NOT NULL;

image.gif

image.gif

二、外键的优缺点

2.1 外键缺点

  • 改、删时要考虑外键:每次做DELETE 或者UPDATE都必须考虑外键约束,不方便。
  • 表级锁导致并发差:并发问题外键约束会启用行级锁主表写入时会进入阻塞
  • 级联删除问题:删除主表的一条记录,该记录外键关联的从表记录也会随之删除,导致数据不可控。例如删除“订单表”的一条订单,关联的“订单详情表”的一条记录也会随之删除。
  • 耦合高、迁移麻烦:主表从表之间互相耦合,主表数据量过大要分表并迁移数据时,就必须先删除外键,不然你刚删完主表的一条记录,从表关联记录也级联删除了,导致数据丢失。

image.gif

2.2 外键优点

  • 数据一致性:数据库通过外键可以保证数据的完整性和一致性。因为在更新主表记录时,从表对应的记录也会随之更改,并且更改时会加表级锁,以牺牲并发性为代价,保证数据的一致性。例如删除“订单表”的一条订单,关联的“订单详情表”的一条记录也会随之删除。
  • 增加ER图的可读性:通过外键,可以更直观的看出表与表之间的关系。

image.gif

三、适用场景

3.1 哪些情况下不要用外键?为什么互联网大厂禁用外键约束?

综合对比外键的优缺点,可以得出结论:

并发量高、表数据量大的分布式项目适合使用外键。防止每次更新数据时都要加表级锁,维护外键的一致性。

因为互联网大厂的产品并发量高,并且一般是分布式项目,为了提高数据库的并发性能,一般都禁用外键,在业务层面实现数据一致性,例如删除“订单表”一条记录前,先关联查询“订单详情表”的对应记录,然后先后一起删除。

3.2 哪些情况下可以用外键?

综合对比外键的优缺点,可以得出结论:

并发量不高、表数据量不大、对数据一致性要求较高的单体式项目适合使用外键。

相关文章
|
存储 算法 NoSQL
还分不清 Cookie、Session、Token、JWT?看这一篇就够了
Cookie、Session、Token 和 JWT(JSON Web Token)都是用于在网络应用中进行身份验证和状态管理的机制。虽然它们有一些相似之处,但在实际应用中有着不同的作用和特点,接下来就让我们一起看看吧,本文转载至http://juejin.im/post/5e055d9ef265da33997a42cc
50322 14
|
设计模式 前端开发 Java
DTO和VO的区别及使用场景详解
DTO和VO的区别及使用场景详解
8365 1
|
存储 SQL 缓存
Hadoop入门(一篇就够了)
Hadoop入门(一篇就够了)
37348 4
Hadoop入门(一篇就够了)
|
Java Spring 容器
一文带你深入理解SpringBean生命周期之Aware详解
一文带你深入理解SpringBean生命周期之Aware详解
2411 2
一文带你深入理解SpringBean生命周期之Aware详解
|
XML 域名解析 JSON
【RESTful】RESTful API 接口设计规范 | 示例
【RESTful】RESTful API 接口设计规范 | 示例
13854 0
【RESTful】RESTful API 接口设计规范 | 示例
|
索引 存储 数据库
数据库设计规范
基于阿里数据库设计规范扩展而来
51235 4
|
关系型数据库 MySQL 数据库
MySQL - 不使用外键约束的实操(二)
MySQL - 不使用外键约束的实操(二)
1137 0
|
10月前
|
XML 人工智能 Java
注入Java Bean的方式
本文总结了 Spring Boot 中常见的 Bean 注入方式,包括字段注入(`@Autowired`)、构造器注入(推荐)、Setter 方法注入、`@Resource` 按名称注入、`@Bean` 定义复杂 Bean、`@Value` 注入配置值、XML 配置、`ApplicationContextAware` 手动获取 Bean 以及 JSR-330 的 `@Inject`。同时分析了 Setter 注入逐渐被淡化的原因,强调构造器注入的不可变性和安全性优势,并推荐结合 Lombok 简化代码。文章还提供了按需选择注解的建议和最佳实践,帮助开发者根据场景选择合适的依赖注入方式。
863 49
|
缓存 安全 Java
Spring Boot 3 集成 Spring Security + JWT
本文详细介绍了如何使用Spring Boot 3和Spring Security集成JWT,实现前后端分离的安全认证概述了从入门到引入数据库,再到使用JWT的完整流程。列举了项目中用到的关键依赖,如MyBatis-Plus、Hutool等。简要提及了系统配置表、部门表、字典表等表结构。使用Hutool-jwt工具类进行JWT校验。配置忽略路径、禁用CSRF、添加JWT校验过滤器等。实现登录接口,返回token等信息。
7033 14
Spring Boot 3 集成 Spring Security + JWT
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
2126 24
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存