数据库的外键约束,可以让数据进行一致性更新,但是会有一定的性能损耗,线上业务使用不多。通常上述级联更新和删除都是由应用层业务逻辑进行判断并实现。
---- 表结构 摘自 MySQL 官方文档--mysql> create table parent (-> id int not null,-> primary key (id)-> ) engine=innodb;Query OK, 0 rows affected (0.14 sec)mysql> create table child (-> id int,-> parent_id INT,-> index par_ind (parent_id),-> foreign key (parent_id)-> references parent(id)-> on delete cascade on update cascade -- 比官网例子增加 update cascade-> ) engine=innodb;Query ok, 0 rows affected (0.15 sec)mysql> insert into child values(1,1); -- 我们插入一条数据,id=1,parent_id=1ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`burn_test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON DELETE CASCADE)-- 直接报错了,因为此时parent表中没有任何记录mysql> insert into parent values(1); -- 现在parent中插入记录Query OK, 1 row affected (0.03 sec)mysql> insert into child values(1,1); -- 然后在child中插入记录,且parent_id是在parent中存在的Query OK, 1 row affected (0.02 sec)mysql> insert into child values(1,2); -- 插入parent_id=2的记录,报错。因为此时parent_id=2的记录不存在ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`burn_test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON DELETE CASCADE)mysql> select * from child;+------+-----------+| id | parent_id |+------+-----------+| 1 | 1 | -- parent_id = 1+------+-----------+1 row in set (0.00 sec)mysql> select * from parent;+----+| id |+----+| 1 | -- 根据表结构的定义(Foreign_key),这个值就是 child表中的id+----+1 row in set (0.00 sec)mysql> update parent set id=100 where id=1;Query OK, 1 row affected (0.04 sec)Rows matched: 1 Changed: 1 Warnings: 0mysql> select * from parent;+-----+| id |+-----+| 100 | -- 已经设置成了100+-----+1 row in set (0.00 sec)mysql> select * from child;+------+-----------+| id | parent_id |+------+-----------+| 1 | 100 | -- 自动变化,这是on update cascade的作用,联级更新,parent更新,child也跟着更新+------+-----------+1 row in set (0.00 sec)mysql> delete from parent where id=100; -- 删除这条记录Query OK, 1 row affected (0.03 sec)mysql> select * from parent; -- id=100的记录已经被删除了Empty set (0.00 sec)mysql> select * from child; -- id=1,parent_id=100的记录跟着被删除了。on delete cascade的作用Empty set (0.00 sec)mysql> alter table child drop foreign key child_ibfk_1; -- 删除 之前的外键Query OK, 0 rows affected (0.07 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> alter table child add foreign key(parent_id)-> references parent(id) on update cascade on delete restrict; -- 使用严格模式Query OK, 0 rows affected (0.27 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> insert into parent values(50);Query OK, 1 row affected (0.03 sec)mysql> insert into child values(3,50);Query OK, 1 row affected (0.03 sec)mysql> insert into child values(3,51); -- 和之前一样会提示错误ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`burn_test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON UPDATE CASCADE)mysql> delete from parent where id=50; -- 删除失败了,因为是restrict模式ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`burn_test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON UPDATE CASCADE)-- 注意,delete 后面说明都不写表示 no action == restrict
作者:殷建卫 链接:https://www.yuque.com/yinjianwei/vyrvkf 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
