外键主要用于引用完整性的约束检查。在 InnoDB存储引擎中,对于一个外键列,如果没有显式地对这个列加索引, InnoDB存储引擎自动对其加一个索引,因为这样可以避免表锁——这比 Oracle数据库做得好, Oracle数据库不会自动添加索引,用户必须自已手动添加,这也导致了 Oracle数据库中可能产生死锁。
对于外键值的插入或更新,首先需要查询父表中的记录,即 SELECT父表。但是对于父表的 SELECT操作,不是使用一致性非锁定读的方式,因为这样会发生数据不一致的问题,因此这时使用的是 SELECT… LOCK IN SHARE MODE方式,即主动对父表加一个S锁。如果这时父表上已经这样加X锁,子表上的操作会被阻塞,如下表所示。
时间 | 会话A | 会话B |
---|---|---|
时间 | 会话A | 会话B |
1 | BEGIN | |
2 | DELETEFROMparentWHEREid=3; | |
3 | BEGIN | |
4 | INSERTINTOchildSELECT2,3;#第二列是外键,执行该句时被阻塞(waiting) |
在上述的例子中,两个会话中的事务都没有进行COMMIT或ROLLBAGK操作,而会话B的操作会被阻塞。这是因为id为3的父表在会话A中已经加了一个X锁,而此时在会话B中用户又需要对父表中id为3的行加一个S锁,这时INSERT的操作会被阻塞。设想如果访问父表时,使用的是一致性的非锁定读,这时 Session B会读到父表有id=3的记录,可以进行插入操作。但是如果会话A对事务提交了,则父表中就不存在id为3的记录。数据在父、子表就会存在不一致的情况。若这时用户查询INNODB_LOCKS表,会看到如下结果:
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。