一、前言
對于【是否使用外鍵約束】這個話題已經是老生常談的了,在學校中,老師交給我們的大多是需要我們建立外鍵約束,但進入了實際作業很多時候并不會使用外鍵,而是通過代碼邏輯來控制,包括在阿里的JAVA規范中也明確規定:【強制】不得使用外鍵與級聯,一切外鍵概念必須在應用層解決,
為什么要做這樣的規定呢?到底該不該使用外鍵約束呢?我們可以舉一個例子來說明
二、舉例說明
現在我們在資料庫中建立了兩張表:【product和project】,【project】的porduct欄位,關聯Product,他們之間存在下圖這樣的一條外鍵記錄:

當我們對【project】表增加一條project_id為 1 的記錄的時候,由于【product】表不存在相應的記錄會導致報錯:

可以看出,這個約束的存在,會保證表間資料的關系的完整性,更不容易出現臟資料,這是外鍵約束非常明顯的優點!
總結一下,外鍵約束具有如下的優點:
- 保證資料的完整性和一致性
- 級聯操作方便
- 將資料完整性判斷托付給了資料庫完成,減少了程式的代碼量
但也存在著不可忽略的缺點:
性能問題
我們剛建立了兩張表【project】和【product】,【project】表通過project_id欄位與【product】表做了外鍵約束,
這個時候,當我們每次往【project】表插入資料的時候,它會先去【product】中查詢是否有對應的關聯資料,如果通程序式來控制可以不進行這次查詢,但設立了外鍵約束,就一定會去進行該查詢,這實際是冗余的,當關聯的欄位少的時候可能沒啥影響,但一但關聯欄位多了后,這種影響就尤其明顯!
死鎖
外鍵導致查詢需要依賴其他資料表,這意味著 InnoDB 需要在父級表(或相關表)中檢驗相應的值,這也會鎖定父級表的資料行,以保證在事務完成前該行不會被洗掉,這會導致意外的鎖等待,甚至是死鎖,這類問題很難被定位,
分庫分表困難
加了約束的資料庫在需要分庫分表的情況下,會特別困難
開發/測驗效率的降低
在我們日常的測驗程序中,經常會遇到發現了一個BUG想復現或者方便測驗的情況,會直接改資料庫表的資料來達到方便測驗的效果,
雖然這及不規范,但實際情況就是能夠提升我們很多效率,這是毋庸置疑的!可是,這樣的操作也會帶來一些問題,比如因為資料導致的BUG,但實際并不是程式的BUG,或者發現不了一些潛在的BUG,
三、總結
目前很多互聯網公司,特別是大廠對于外鍵的態度都是要求禁用,這其實不單單因為性能問題,主要也因為互聯網的業務變化快,會間接導致表結構容易發生變動,很可能會因為外鍵約束的存在導致導意想不到的問題和開發效率的降低,因此,在非必要的情況、不需要高可靠性的業務場景下,不建議使用外鍵約束,這樣更能夠擁抱變化,
但我們并不能一桿子打死,因為有的業務場景反而使用外鍵約束更好,比如政務、銀行、軍工等需要資料高可靠的情況下,所以我的建議是:如果是業務相對復雜的話,可以在測驗環境使用外鍵約束,但上了生產環境需要去掉,如果業務相對簡單,那完全可以洗掉外鍵約束,但對于銀行、軍工行業這些不允許資料出錯,需要高可靠性的場景下,還是建議建立外鍵約束,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/330236.html
標籤:其他
上一篇:MySQL 資料庫簡介
