数据库的外键约束,可以让数据进行一致性更新,但是会有一定的性能损耗,线上业务使用不多。通常上述级联更新和删除都是由应用层业务逻辑进行判断并实现。

    1. --
    2. -- 表结构 摘自 MySQL 官方文档
    3. --
    4. mysql> create table parent (
    5. -> id int not null,
    6. -> primary key (id)
    7. -> ) engine=innodb;
    8. Query OK, 0 rows affected (0.14 sec)
    9. mysql> create table child (
    10. -> id int,
    11. -> parent_id INT,
    12. -> index par_ind (parent_id),
    13. -> foreign key (parent_id)
    14. -> references parent(id)
    15. -> on delete cascade on update cascade -- 比官网例子增加 update cascade
    16. -> ) engine=innodb;
    17. Query ok, 0 rows affected (0.15 sec)
    18. mysql> insert into child values(1,1); -- 我们插入一条数据,id=1parent_id=1
    19. 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)
    20. -- 直接报错了,因为此时parent表中没有任何记录
    21. mysql> insert into parent values(1); -- 现在parent中插入记录
    22. Query OK, 1 row affected (0.03 sec)
    23. mysql> insert into child values(1,1); -- 然后在child中插入记录,且parent_id是在parent中存在的
    24. Query OK, 1 row affected (0.02 sec)
    25. mysql> insert into child values(1,2); -- 插入parent_id=2的记录,报错。因为此时parent_id=2的记录不存在
    26. 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)
    27. mysql> select * from child;
    28. +------+-----------+
    29. | id | parent_id |
    30. +------+-----------+
    31. | 1 | 1 | -- parent_id = 1
    32. +------+-----------+
    33. 1 row in set (0.00 sec)
    34. mysql> select * from parent;
    35. +----+
    36. | id |
    37. +----+
    38. | 1 | -- 根据表结构的定义(Foreign_key),这个值就是 child表中的id
    39. +----+
    40. 1 row in set (0.00 sec)
    41. mysql> update parent set id=100 where id=1;
    42. Query OK, 1 row affected (0.04 sec)
    43. Rows matched: 1 Changed: 1 Warnings: 0
    44. mysql> select * from parent;
    45. +-----+
    46. | id |
    47. +-----+
    48. | 100 | -- 已经设置成了100
    49. +-----+
    50. 1 row in set (0.00 sec)
    51. mysql> select * from child;
    52. +------+-----------+
    53. | id | parent_id |
    54. +------+-----------+
    55. | 1 | 100 | -- 自动变化,这是on update cascade的作用,联级更新,parent更新,child也跟着更新
    56. +------+-----------+
    57. 1 row in set (0.00 sec)
    58. mysql> delete from parent where id=100; -- 删除这条记录
    59. Query OK, 1 row affected (0.03 sec)
    60. mysql> select * from parent; -- id=100的记录已经被删除了
    61. Empty set (0.00 sec)
    62. mysql> select * from child; -- id=1parent_id=100的记录跟着被删除了。on delete cascade的作用
    63. Empty set (0.00 sec)
    64. mysql> alter table child drop foreign key child_ibfk_1; -- 删除 之前的外键
    65. Query OK, 0 rows affected (0.07 sec)
    66. Records: 0 Duplicates: 0 Warnings: 0
    67. mysql> alter table child add foreign key(parent_id)
    68. -> references parent(id) on update cascade on delete restrict; -- 使用严格模式
    69. Query OK, 0 rows affected (0.27 sec)
    70. Records: 0 Duplicates: 0 Warnings: 0
    71. mysql> insert into parent values(50);
    72. Query OK, 1 row affected (0.03 sec)
    73. mysql> insert into child values(3,50);
    74. Query OK, 1 row affected (0.03 sec)
    75. mysql> insert into child values(3,51); -- 和之前一样会提示错误
    76. 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)
    77. mysql> delete from parent where id=50; -- 删除失败了,因为是restrict模式
    78. 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)
    79. -- 注意,delete 后面说明都不写表示 no action == restrict

    作者:殷建卫 链接:https://www.yuque.com/yinjianwei/vyrvkf 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。