Mysql關(guān)于數(shù)據(jù)庫(kù)是否應(yīng)該使用外鍵約束詳解說(shuō)明
一、
對(duì)于【是否使用外鍵約束】這個(gè)話(huà)題已經(jīng)是老生常談的了。在學(xué)校中,老師交給我們的大多是需要我們建立外鍵約束,但進(jìn)入了實(shí)際工作很多時(shí)候并不會(huì)使用外鍵,而是通過(guò)代碼邏輯來(lái)控制。包括在阿里的JAVA規(guī)范中也明確規(guī)定:【強(qiáng)制】不得使用外鍵與級(jí)聯(lián),一切外鍵概念必須在應(yīng)用層解決。
為什么要做這樣的規(guī)定呢?到底該不該使用外鍵約束呢?我們可以舉一個(gè)例子來(lái)說(shuō)明
二、舉例說(shuō)明
現(xiàn)在我們?cè)跀?shù)據(jù)庫(kù)中建立了兩張表:【product和project】,【project】的porduct
字段,關(guān)聯(lián)Product
,他們之間存在下圖這樣的一條外鍵記錄:
當(dāng)我們對(duì)【project】表增加一條project_id
為 1 的記錄的時(shí)候,由于【product】表不存在相應(yīng)的記錄會(huì)導(dǎo)致報(bào)錯(cuò):
可以看出,這個(gè)約束的存在,會(huì)保證表間數(shù)據(jù)的關(guān)系的完整性。更不容易出現(xiàn)臟數(shù)據(jù)。這是外鍵約束非常明顯的優(yōu)點(diǎn)!
總結(jié)一下,外鍵約束具有如下的優(yōu)點(diǎn):
- 保證數(shù)據(jù)的完整性和一致性
- 級(jí)聯(lián)操作方便
- 將數(shù)據(jù)完整性判斷托付給了數(shù)據(jù)庫(kù)完成,減少了程序的代碼量
但也存在著不可忽略的缺點(diǎn):
性能問(wèn)題
我們剛建立了兩張表【project】和【product】,【project】表通過(guò)project_id
字段與【product】表做了外鍵約束。
這個(gè)時(shí)候,當(dāng)我們每次往【project】表插入數(shù)據(jù)的時(shí)候,它會(huì)先去【product】中查詢(xún)是否有對(duì)應(yīng)的關(guān)聯(lián)數(shù)據(jù),如果通過(guò)程序來(lái)控制可以不進(jìn)行這次查詢(xún)。但設(shè)立了外鍵約束,就一定會(huì)去進(jìn)行該查詢(xún)。這實(shí)際是冗余的。當(dāng)關(guān)聯(lián)的字段少的時(shí)候可能沒(méi)啥影響,但一但關(guān)聯(lián)字段多了后,這種影響就尤其明顯!
死鎖
外鍵導(dǎo)致查詢(xún)需要依賴(lài)其他數(shù)據(jù)表,這意味著 InnoDB 需要在父級(jí)表(或相關(guān)表)中檢驗(yàn)相應(yīng)的值。這也會(huì)鎖定父級(jí)表的數(shù)據(jù)行,以保證在事務(wù)完成前該行不會(huì)被刪除。這會(huì)導(dǎo)致意外的鎖等待,甚至是死鎖,這類(lèi)問(wèn)題很難被定位。
分庫(kù)分表困難
加了約束的數(shù)據(jù)庫(kù)在需要分庫(kù)分表的情況下,會(huì)特別困難
開(kāi)發(fā)/測(cè)試效率的降低
在我們?nèi)粘5臏y(cè)試過(guò)程中,經(jīng)常會(huì)遇到發(fā)現(xiàn)了一個(gè)BUG想復(fù)現(xiàn)或者方便測(cè)試的情況,會(huì)直接改數(shù)據(jù)庫(kù)表的數(shù)據(jù)來(lái)達(dá)到方便測(cè)試的效果。
雖然這及不規(guī)范,但實(shí)際情況就是能夠提升我們很多效率。這是毋庸置疑的!可是,這樣的操作也會(huì)帶來(lái)一些問(wèn)題,比如因?yàn)閿?shù)據(jù)導(dǎo)致的BUG,但實(shí)際并不是程序的BUG,或者發(fā)現(xiàn)不了一些潛在的BUG。
三、總結(jié)
目前很多互聯(lián)網(wǎng)公司,特別是大廠(chǎng)對(duì)于外鍵的態(tài)度都是要求禁用。這其實(shí)不單單因?yàn)樾阅軉?wèn)題,主要也因?yàn)榛ヂ?lián)網(wǎng)的業(yè)務(wù)變化快,會(huì)間接導(dǎo)致表結(jié)構(gòu)容易發(fā)生變動(dòng),很可能會(huì)因?yàn)橥怄I約束的存在導(dǎo)致導(dǎo)意想不到的問(wèn)題和開(kāi)發(fā)效率的降低。因此,在非必要的情況、不需要高可靠性的業(yè)務(wù)場(chǎng)景下,不建議使用外鍵約束,這樣更能夠擁抱變化。
但我們并不能一桿子打死,因?yàn)橛械臉I(yè)務(wù)場(chǎng)景反而使用外鍵約束更好,比如政務(wù)、銀行、軍工等需要數(shù)據(jù)高可靠的情況下。所以我的建議是:如果是業(yè)務(wù)相對(duì)復(fù)雜的話(huà),可以在測(cè)試環(huán)境使用外鍵約束,但上了生產(chǎn)環(huán)境需要去掉。如果業(yè)務(wù)相對(duì)簡(jiǎn)單,那完全可以刪除外鍵約束。但對(duì)于銀行、軍工行業(yè)這些不允許數(shù)據(jù)出錯(cuò),需要高可靠性的場(chǎng)景下,還是建議建立外鍵約束。
到此這篇關(guān)于Mysql關(guān)于數(shù)據(jù)庫(kù)是否應(yīng)該使用外鍵約束詳解說(shuō)明的文章就介紹到這了,更多相關(guān)Mysql 數(shù)據(jù)庫(kù)外鍵約束內(nèi)容請(qǐng)搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!
版權(quán)聲明:本站文章來(lái)源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來(lái)源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來(lái)源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來(lái),僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。