什么时候适合使用外键,什么时候不适合使用外键,使用外键有什么好处和坏处?
外键的好处:可以使得两张表关联,保证数据的一致性和实现一些级联操作。但是外键是否采用看业务应用场景,以及开发成本的,大致列下什么时候适合,什么时候不适合使用:
1. 互联网行业应用不推荐使用外键: 用户量大,并发度高,为此数据库服务器很容易成为性能瓶颈,尤其受IO能力限制,且不能轻易地水平扩展;若是把数据一致性的控制放到事务中,也即让应用服务器承担此部分的压力,而引用服务器一般都是可以做到轻松地水平的伸缩;【不适合】
2.传统行业【适合】
1>.软件应用的人数有限,换句话说是可控的;
2>.数据库服务器的数据量也一般不会超大,且活跃数据有限;
综合上述2句话描述,也即数据库服务器的性能不是问题,所以不用过多考虑性能的问题;另外,使用外键可以降低开发成本,借助数据库产品自身的触发器可以实现表与关联表之间的数据一致性和更新;最后一点,使用外键的方式,还可以做到开发人员和数据库设计人员的分工,可以为程序员承担更多的工作量;
为何说外键有性能问题:
1.数据库需要维护外键的内部管理;
2.外键等于把数据的一致性事务实现,全部交给数据库服务器完成;
3.有了外键,当做一些涉及外键字段的增,删,更新操作之后,需要触发相关操作去检查,而不得不消耗资源;
4.外键还会因为需要请求对其他表内部加锁而容易出现死锁情况;
二、使用方法
1、创建外键的语法:
外键的定义语法:
[CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...)
REFERENCES tbl_name (index_col_name, ...)
[ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
该语法可以在 CREATE TABLE 和 ALTER TABLE 时使用,如果不指定CONSTRAINT symbol,MYSQL会自动生成一个名字。
ON DELETE、ON UPDATE表示事件触发限制,可设参数:
① RESTRICT(限制外表中的外键改动,默认值)
② CASCADE(跟随外键改动)
③ SET NULL(设空值)
④ SET DEFAULT(设默认值)
⑤ NO ACTION(无动作,默认的)
在父表上进行update/delete以更新或删除在子表中有一条或多条对应匹配行的候选键时,父表的行为取决于:在定义子表的外键时指定的on update/on delete子句。
关键字 |
含义 |
CASCADE |
删除包含与已删除键值有参照关系的所有记录 |
SET NULL |
修改包含与已删除键值有参照关系的所有记录,使用NULL值替换(只能用于已标记为NOT NULL的字段) |
RESTRICT |
拒绝删除要求,直到使用删除键值的辅助表被手工删除,并且没有参照时(这是默认设置,也是最安全的设置) |
NO ACTION |
啥也不做 |
示例:
CREATE TABLE `task_basic` (
`task_id` int(10) NOT NULL AUTO_INCREMENT,
`task_name` varchar(128) NOT NULL DEFAULT '',
`description` varchar(1024) NOT NULL DEFAULT '',
`last_modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`task_id`)
) ENGINE=InnoDB CHARSET=utf8
CREATE TABLE `job` (
`job_id` int(10) NOT NULL AUTO_INCREMENT,
`task_id` int(10) NOT NULL DEFAULT '0',
`job_status` int(10) NOT NULL DEFAULT '0',
`last_modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`job_id`),
KEY `task_id` (`task_id`),
CONSTRAINT `job_ibfk_1` FOREIGN KEY (`task_id`) REFERENCES `task_basic` (`task_id`)
) ENGINE=InnoDB CHARSET=utf8
insert task_basic (task_name) values ('aaa') ,('bbb') ,('ccc'), ('ddd');
insert job ('task_id') values (1),(4);
insert job (task_id) values (1),(5); #失败,因为所依赖表中没有 task_id=5的外键
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`job`, CONSTRAINT `job_ibfk_1` FOREIGN KEY (`task_id`) REFERENCES `task_basic` (`task_id`))
delete from task_basic where task_id = 1; #失败,因为默认外键是 restrict模式
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`job`, CONSTRAINT `job_ibfk_1` FOREIGN KEY (`task_id`) REFERENCES `task_basic` (`task_id`))
删除外键
语法: ALTER TABLE table-name DROP FOREIGN KEY key-id;
例: ALTER TABLE `tb_active` DROP FOREIGN KEY `FK_ID`
来源:oschina
链接:https://my.oschina.net/u/347414/blog/737451