前言
MySQL 外键 (FOREIGNKEY) 是表的一个非凡字段,用来建设主表与从表的关联关系,为两个表的数据建设连贯,束缚两个表中数据的一致性和完整性。
之前的第一篇文章相干文章(「技术探讨」为什么大家很少应用外键了?),总结了一些不应用外键的场景以及应用外键的劣势之处。
本篇文章会基于实例来阐明外键束缚虽会保障表间数据的关系“始终残缺统一”,但在实际操作中,每次做 DELETE 或者 UPDATE 都必须思考外键束缚,会导致开发的时候很苦楚。
保持数据的一致性和完整性,次要体现在上面两个方面:
阻止执行
从表插入新行,其外键值不是主表的主键值便阻止插入;
从表批改外键值,新值不是主表的主键值便阻止批改;
主表删除行,其主键值在从表里存在便阻止删除(要想删除,必须先删除从表的相干行);
主表批改主键值,旧值在从表里存在便阻止批改(要想批改,必须先删除从表的相干行)。
级联执行
主表删除行,连带从表的相干行一起删除;
主表批改主键值,连带从表相干行的外键值一起批改。
上面咱们举个例子来阐明一下:
1. 创立两个 table,“教练”和“学员”,table“学员”带有外键束缚。
CREATE TABLE jiaolian(
`jiaolian_id` INT AUTO_INCREMENT,
`jiaolian_name` VARCHAR(30),
PRIMARY KEY (`jiaolian_id`));
CREATE TABLE xueyuan(
`xueyuan_id` INT AUTO_INCREMENT,
`jiaolian_id` INT,
`xueyuan_name` VARCHAR(30),
FOREIGN KEY (`jiaolian_id`) REFERENCES `jiaolian` (`jiaolian_id`),
PRIMARY KEY (`xueyuan_id`));
- 减少两个“教练”,两个“学员”。
insert into jiaolian(jiaolian_name) values("司机老李");
insert into jiaolian(jiaolian_name) values("司机老林");
insert into xueyuan(jiaolian_id,xueyuan_name) values(1,"师傅张三");
insert into xueyuan(jiaolian_id,xueyuan_name) values(2,"师傅李四");
3. 再减少一个“学员”,不存在的 jiaolian_id,执行失败了。
insert into xueyuan(jiaolian_id,xueyuan_name) values(3,"师傅王五"); #error
-
删除一个“教练”,“教练”有关联的“学员”,执行失败。
delete from jiaolian where jiaolian_name="司机老李"; #error
- 先删除“教练”关联的“学员”,再删除“教练”,执行胜利
delete from xueyuan where xueyuan_name="师傅张三";
delete from jiaolian where jiaolian_name="司机老李";
论断
通过这个例子,咱们能够看到,外键束缚会保障表间数据的关系“始终残缺统一”。
尽管将数据的一致性和完整性判断托付给了数据库实现,缩小了程序的代码量。但在实际操作中,每次做 DELETE 或者 UPDATE 都必须思考外键束缚,会导致开发的时候很苦楚,测试数据极为不不便。
在应用外键的状况下,每次批改数据都须要去另外一个表检查数据,须要获取额定的锁。
在高并发大流量事务场景,应用外键可能容易造成死锁,以及数据库资源呈现瓶颈,所以个别互联网行业高频率高并发不倡议应用。
一般来说,在业务代码中实现的时候,只有在应用层依照设计之初的这种固有关联逻辑,来解决数据即可,并不需要在数据库层面进行外键束缚。
KunlunDB 我的项目已开源
【GitHub:】
https://github.com/zettadb
【Gitee:】
https://gitee.com/zettadb
END