InnoDB的外键约束

原文地址: https://dev.mysql.com/doc/refman/8.0/en/innodb-foreign-key-constraints.html

这一章节会介绍InnoDB存储引擎如何处理外键约束,主要包括以下几个主题:

  • 外键的定义

  • 关联操作

  • 外键在Generated Column和虚拟索引上的使用限制

对于外键如何使用的信息和例子,请查看第13.1.20.6节 使用外键约束

外键定义

InnoDB表的外键定义符合以下条件:

  • InnoDB允许外键关联任何有索引的一列或多列。但是,被关联的表中必须保证被关联的列是索引的第一列。InnoDB添加到索引里的隐藏列也算作是第一列(请查看第15.6.2.1节 聚簇索引和二级索引)。

  • InnoDB不支持为用户自定义分区的表定义外键。这意味这只有非用户自定义分区的InnoDB表存在外键或者被外键索引的列。

  • InnoDB允许外键关联一个非唯一键。这是InnoDB对标准SQL的扩展。

关联操作

InnoDB表外键的关联行为受下列行为影响:

  • 如果MySQL服务器允许SET DEFAULT,会被InnoDB拒绝生效。InnoDB不允许CREATE TABLEALTER TABLE语句使用此语法。

  • 如果父表中有相同的被关联的索引的数据行,InnoDB执行外键检测就好像父表中拥有相同索引值的其他行不存在。例如,你已经定义了一个RESTRICT类型约束,并且一个子数据行有多个父数据行,InnoDB不允许删除这些父数据行中的任意一行。

  • InnoDB通过深度优先算法执行级联操作,基于外键相关的索引中的记录。

  • 如果ON UPDATE CASCADE或者ON UPDATE SET NULL在级联操作时递归的更新它之前已经更新的表,它表现的如同RESTRICT。这意味着你不能使用关联本身的ON UPDATE CASCADE或ON UPDATE SET NULL操作。这样处理是为了避免级联更新时无限循环。另一方面,关联自身的ON DELETE SET NULL有可能和ON DELETE CASCADE。级联操作不能嵌套操作15层。

  • 和MySQL的惯例一致,一个SQL语句增删改很多行数据,InnoDB会逐行检查唯一键和外键约束。当执行外键约束时,InnoDB对它已经扫描到的子数据行或父数据行施加行级的共享锁。InnoDB会即时检查外键约束,而不是推迟到事务提交。根据SQL标准,默认的行为应该要延迟检查。即当整个SQL语句已经执行完之后再做约束见检查。在InnoDB实现延迟的约束检查之前,一些事还无法实现,例如使用外键关联自己的删除记录操作。

外键在Generated Column和虚拟索引上的使用限制

  • 在一个stored generated column上外键不能使用CASCADE,SET NULL,或SET DEFAULT as ON UPDATE进行关联操作,也不能使用SET NULL或者SET DEFAULT as ON DELETE关联操作。

  • 外键在stored generated column的源字段上限制使用CASCADE,SET NULL,或者SET DEFAULT as ON UPDATE 或 ON DELETE 的关联操作。

  • 外键无法关联virtual generated column

  • MySQL8.0之前,外键无法关联建立在virtual generated column列上的二级索引。