乐趣区

关于数据库:为什么大家很少使用外键了二

​前言

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`));
  1. 减少两个“教练”,两个“学员”。
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
  1. 删除一个“教练”,“教练”有关联的“学员”,执行失败。

    delete from jiaolian where jiaolian_name="司机老李";  #error
  1. 先删除“教练”关联的“学员”,再删除“教练”,执行胜利
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

退出移动版