MySQL不支持的功能
MySQL不支持的功能
本節(jié)介紹其他數(shù)據(jù)庫(kù)中有而MySQL中無(wú)的功能。它介紹省略了什么功能,以及在需要這些功能時(shí)怎么辦。一般情況下, MySQL之所以忽略某些功能是因?yàn)樗鼈冇胸?fù)面性能影響。有的功能正在開發(fā)者的計(jì)劃清單上,一旦找到一種方法可以實(shí)現(xiàn)相應(yīng)的功能而又不致于影響
良好性能的目標(biāo),就會(huì)對(duì)它們進(jìn)行實(shí)現(xiàn)。
■ 子選擇。子選擇是嵌套在另一個(gè)SELECT 語(yǔ)句內(nèi)的SELECT 語(yǔ)句,如下面的查詢所示:
SELECT * FROM score
WHERE event_id IN (SELECT event_id FROM event WHERE type = "T")
子選擇打算在MySQL3.24 中給出,到那時(shí)它們就不會(huì)忽略了。但到那時(shí),許多用子選擇撰寫的查詢也可以用連接來(lái)編寫。請(qǐng)參閱3 . 8 . 1節(jié)“將子選擇編寫為連接”。
■ 事務(wù)處理和提交/回退。事務(wù)處理是由其他客戶機(jī)作為一個(gè)整體不中斷執(zhí)行的一組SQL語(yǔ)句。提交/回退功能允許規(guī)定數(shù)條語(yǔ)句作為一個(gè)整體執(zhí)行或不執(zhí)行。即,如果事務(wù)處理中的任何一條語(yǔ)句失敗,那么直到該語(yǔ)句前執(zhí)行的所有語(yǔ)句的作用都被撤消。
ySQL 自動(dòng)進(jìn)行單一SQL 語(yǔ)句的同步以免客戶機(jī)互相干擾。(例如,兩個(gè)客戶機(jī)不能對(duì)相同的表進(jìn)行同時(shí)寫入。)此外,可利用LOCK TABLES 和UNLOCK TABLES將數(shù)條語(yǔ)句組成一個(gè)整體,這使您能夠完成單條語(yǔ)句的并發(fā)控制所不能滿足的操作。MySQL與事務(wù)處理有關(guān)的問(wèn)題是,它不能自動(dòng)對(duì)數(shù)條語(yǔ)句進(jìn)行組織,而且如果這些語(yǔ)句中有某一條失敗后也不能對(duì)它們進(jìn)行回退。
為了弄清事務(wù)處理為什么有用,可舉例說(shuō)明。假如您在服裝銷售業(yè)工作,無(wú)論何時(shí),只要您的銷售人員進(jìn)行了一次銷售,都要更新庫(kù)存數(shù)目。下面的例子說(shuō)明了在多個(gè)銷售人員同時(shí)更新數(shù)據(jù)庫(kù)時(shí)可能出現(xiàn)的問(wèn)題(假如初始的襯衫庫(kù)存數(shù)目為4 7):
t1銷售人員1賣出3件襯衫
t2 銷售人員檢索當(dāng)前襯衫計(jì)數(shù)( 4 7):
SELECT quantity FROM inventory WHERE item = "shirt"
t3 銷售人員2賣出2件襯衫
t4 銷售人員2檢索當(dāng)前襯衫計(jì)數(shù)( 4 7)
SELECT quantity FROM inventory WHERE item = "shirt"
t5 銷售人員1計(jì)算庫(kù)存的新數(shù)目為47 - 3 = 44 并設(shè)置襯衫計(jì)數(shù)為44:
UPDATE inventory SET quantity = 44 WHERE item = "shirt"
t6 銷售人員2計(jì)算庫(kù)存的新數(shù)目為47 - 2 = 45 并設(shè)置襯衫計(jì)數(shù)為45:
UPDATE inventory SET quantity = 45 WHERE item = "shirt"
在這個(gè)事件序列結(jié)束時(shí),您已經(jīng)賣掉了5 件襯衫,但庫(kù)存數(shù)目卻是45 而不是4 2。問(wèn)題是如果在一條語(yǔ)句中查看庫(kù)存而在另一條語(yǔ)句中更新其值,這是一個(gè)多語(yǔ)句的事務(wù)處理。第二條語(yǔ)句中所進(jìn)行的活動(dòng)取決于第一條語(yǔ)句中檢索出的值。但是如果在重疊的時(shí)間范圍內(nèi)出現(xiàn)獨(dú)立的事務(wù)處理,則每個(gè)事務(wù)處理的語(yǔ)句會(huì)糾纏在一起,并且互相干擾。在事務(wù)處理型的數(shù)據(jù)庫(kù)中,每個(gè)銷售人員的語(yǔ)句可作為一個(gè)事務(wù)處理執(zhí)行,這樣,銷售人員2 的語(yǔ)句在銷售人員1的語(yǔ)句完成之前不會(huì)被執(zhí)行。在MySQL中,可用兩種方法達(dá)到這個(gè)目的:
■ 方法1:作為一個(gè)整體執(zhí)行一組語(yǔ)句。可利用LOCK TABLES 和UNLOCK TABLES將語(yǔ)句組織在一起,并將它們作為一個(gè)原子單元執(zhí)行:鎖住所需使用的表,發(fā)布查詢,然后釋放這些鎖。這樣阻止了其他人在您鎖住這些表時(shí)使用它們。利用表同步,庫(kù)存情況如下所示:
t1銷售人員1賣出3件襯衫
t2 銷售人員1請(qǐng)求一個(gè)鎖并檢索當(dāng)前襯衫計(jì)數(shù)(47)
LOCK TABLES inventory WRITE
SELECT quantity FROM inventory WHERE item = "shirt"
t3 銷售人員2賣出2件襯衫
t4 銷售人員2試圖取得一個(gè)鎖:這被阻塞,因?yàn)殇N售人員1已經(jīng)占住了鎖:
LOCK TABLES inventory WRITE
t5 銷售人員1計(jì)算庫(kù)存的新數(shù)目為47 - 3 = 44 并設(shè)置襯衫計(jì)數(shù)為44,然后釋放鎖:
UPDATE inventory SET quantity = 44 WHERE item = "shirt"
UNLOCK TABLES
t6 現(xiàn)在銷售人員2的鎖請(qǐng)求成功。銷售人員2檢索當(dāng)前襯衫計(jì)數(shù)( 44)
SELECT quantity FROM inventory WHERE item = "shirt"
t7 銷售人員2計(jì)算庫(kù)存的新數(shù)目為44 - 2 = 42,設(shè)置襯衫計(jì)數(shù)為4 2,然后釋放鎖:
UPDATE inventory SET quantity = 42 WHERE item = "shirt"
UNLOCK TABLES
現(xiàn)在來(lái)自兩個(gè)事務(wù)處理的語(yǔ)句不混淆了,并且?guī)齑嬉r衫數(shù)也正確進(jìn)行了設(shè)置。我們?cè)谶@里使用了一個(gè)WRITE 鎖,因?yàn)槲覀冃枰薷膇nventory 表。如果只是讀取表,可使用READ 鎖。當(dāng)您正在使用表時(shí),這個(gè)鎖允許其他客戶機(jī)讀取表。在剛才舉的例子中,銷售人員2大概不會(huì)注意到執(zhí)行速度上的差異,因?yàn)槠渲械氖聞?wù)處理都很短,執(zhí)行速度很快。但是,作為一個(gè)具有普遍意義的規(guī)則,那就是應(yīng)該盡量避免長(zhǎng)時(shí)間地鎖住表。
如果您正在使用多個(gè)表,那么在您執(zhí)行成組查詢之前,必須鎖住他們。如果只是從某個(gè)特定的表中讀取數(shù)據(jù),那么只需給該表加一個(gè)讀出鎖而不是寫入鎖。假如有一組查詢,其中想對(duì)inventory 表作某些更改,而同時(shí)需要從customer 表中讀取某些數(shù)據(jù)。在此情形下,inventory 表上需要一個(gè)寫入鎖,而customer 表上需要一個(gè)讀出鎖:
LOCK TABLES inventory WRITE,customer READ
...
UNLOCK TABLES
這里要求您自己對(duì)表進(jìn)行加鎖和解鎖。支持事務(wù)處理的數(shù)據(jù)庫(kù)系統(tǒng)將會(huì)自動(dòng)完成這些工作。但是,在作為一個(gè)整體執(zhí)行的分組語(yǔ)句方面,無(wú)論在是否支持事務(wù)處理的數(shù)據(jù)庫(kù)中都是相同的。
■ 方法2:使用相對(duì)更新而不是絕對(duì)更新。要解決來(lái)自多個(gè)事務(wù)處理的語(yǔ)句混淆問(wèn)題,應(yīng)消除語(yǔ)句之間的依賴性。雖然這樣做并不都總是可能的,它只針對(duì)我們的庫(kù)存例子可行。對(duì)于方法1中所用的庫(kù)存更新方法,其中事務(wù)處理需要查看當(dāng)前庫(kù)存數(shù)目,并依據(jù)銷售襯衫的數(shù)目計(jì)算新值,然后更新襯衫的數(shù)目。有可能通過(guò)相對(duì)于當(dāng)前襯衫數(shù)目進(jìn)行計(jì)數(shù)更新,在一個(gè)步驟中完成工作。如下所示:
t1銷售人員1賣出3件襯衫
t2 銷售人員1將襯衫計(jì)數(shù)減3:
UPDATE inventory SET quantity = quantity - 3 WHERE item = "shirt"
t3 銷售人員2賣出2件襯衫
t4 銷售人員2將襯衫計(jì)數(shù)減2:
UPDATE inventory SET quantity = quantity - 2 WHERE item = "shirt"
因此,這里根本不需要多條語(yǔ)句的事務(wù)處理,從而也不需要鎖住表以模擬事務(wù)處理功能。如果所使用的事務(wù)處理類型與這里類似,那么就可以不用事務(wù)處理也能完成工作。上面的例子說(shuō)明了在特殊情形下怎樣避免對(duì)事務(wù)處理功能的需求。但這并不是說(shuō)不存在那種確實(shí)需要事務(wù)處理功能的場(chǎng)合。典型的例子是財(cái)務(wù)轉(zhuǎn)賬,其中錢從一個(gè)賬戶轉(zhuǎn)到另一個(gè)賬戶。假如Bill 給Bob 開了一張$100 的支票,Bob 兌現(xiàn)了這張支票。Bill 的戶頭上應(yīng)該減掉$100 而Bob 的戶頭上應(yīng)該增加相同數(shù)量的錢:
UPDATE account SET balance = balance -100 WHERE name = "Bill"
UPDATE account SET balance = balance +100 WHERE name = "Bob"
如果在這兩條語(yǔ)句執(zhí)行中,系統(tǒng)發(fā)生了崩潰,此事務(wù)處理就不完整了。具有真正事務(wù)處理和提交/回退功能的數(shù)據(jù)庫(kù)系統(tǒng)能夠處理這種情況(至少?gòu)睦碚撋夏軌蛱幚怼D赡苋匀槐仨毰袛嘤龅搅四男┦聞?wù)處理并重新發(fā)布它們,但至少不會(huì)擔(dān)心事務(wù)只處理了一半)。在MySQL中,系統(tǒng)崩潰時(shí)可通過(guò)檢查更新日志來(lái)判斷事務(wù)處理的狀態(tài),雖然這可能需要對(duì)日志進(jìn)行某種手工檢查。
■ 外部鍵和引用完整性。外部鍵允許定義一個(gè)表中的鍵與另一個(gè)表中的鍵相關(guān),而引用完整性允許放置對(duì)包含外部鍵的表可以做什么的約束。例如, samp_db 樣例數(shù)據(jù)庫(kù)的score 表中包含一個(gè)student_id 列,我們用它來(lái)將學(xué)分記錄關(guān)聯(lián)到student 表中的學(xué)生。score.student_id 將定義為支持此概念的數(shù)據(jù)庫(kù)中的一個(gè)外部鍵,我們將在其上加上一條約束,使不能為student 表中不存在的學(xué)生輸入學(xué)分記錄。此外,應(yīng)該允許級(jí)聯(lián)刪除,以便如果某個(gè)學(xué)生從student 表中被刪除后,該學(xué)生的任何學(xué)分記錄將會(huì)自動(dòng)地從
score 表中刪除。
外部鍵有助于保持?jǐn)?shù)據(jù)的一致性,而且還提供了某種方便的手段。MySQL不支持外部鍵的原因主要是由于它對(duì)數(shù)據(jù)庫(kù)的實(shí)現(xiàn)與維護(hù)有負(fù)作用。(MySQL參考指南詳細(xì)列出了這些原因。)注意,對(duì)于外部鍵的這種看法與其他數(shù)據(jù)庫(kù)文獻(xiàn)中的看法有些不同,有的數(shù)據(jù)庫(kù)文獻(xiàn)通常將它們描述成“基本的”。MySQL的開發(fā)者并不贊同這個(gè)觀點(diǎn)。如果您贊成,那么最好是考慮采用其他提供外部鍵支持的數(shù)據(jù)庫(kù)。如果數(shù)據(jù)具有特別復(fù)雜的關(guān)系,您可能不希望擔(dān)負(fù)在應(yīng)用程序中實(shí)現(xiàn)這些相關(guān)性的工作。(即使這樣做的工作量要比增加幾個(gè)額外的DELETE 語(yǔ)句的工作量要稍少一些。)除了在一定程度上能夠在CREATE TABLE 語(yǔ)句中分析FOREIGN KEY 子句外,MySQL不支持外部鍵。(這有助于使從其他數(shù)據(jù)庫(kù)移植代碼到MySQL更為容易。)MySQL不強(qiáng)制讓外部鍵作為一種約束,也不提供級(jí)聯(lián)刪除功能。
外部鍵強(qiáng)制實(shí)施的約束一般不難用程序邏輯來(lái)實(shí)現(xiàn)。有時(shí),它只是一個(gè)怎樣進(jìn)行數(shù)據(jù)錄入處理的問(wèn)題。例如,為了將一個(gè)新記錄插入score 表,不太可能插入不存在的學(xué)生的學(xué)分。顯然,輸入一組學(xué)分的方法應(yīng)該是根據(jù)從student 表得出的學(xué)生名單,對(duì)每個(gè)學(xué)生,取其學(xué)分并利用該學(xué)生的ID 號(hào)產(chǎn)生一個(gè)score 表的記錄。對(duì)于這個(gè)過(guò)程,不存在錄入一個(gè)不存在的學(xué)生的記錄的可能。您不會(huì)憑空造出一個(gè)學(xué)分記錄來(lái)插入score 表。要實(shí)現(xiàn)DELETE 的級(jí)聯(lián)效果,必須用自己的應(yīng)用程序邏輯來(lái)完成。假如想要?jiǎng)h除13 號(hào)學(xué)生。這也隱含表示需要?jiǎng)h除該學(xué)生的學(xué)分記錄。在支持級(jí)聯(lián)刪除的數(shù)據(jù)庫(kù)中,只需要用如下的語(yǔ)句就可以刪除student 表的記錄和相應(yīng)的score 表的記錄:
DELETE FROM student WHERE student_id = 13
而在MySQL中,必須明確地用DELETE 語(yǔ)句自己進(jìn)行第二個(gè)刪除語(yǔ)句:
DELETE FROM student WHERE student_id = 13
DELETE FROM score WHERE student_id = 13
■ 存儲(chǔ)過(guò)程和觸發(fā)器。存儲(chǔ)過(guò)程是編譯和存放在服務(wù)器中的SQL 代碼。它可在以后調(diào)用而無(wú)需從客戶機(jī)發(fā)送并分析。可以對(duì)一個(gè)過(guò)程進(jìn)行更改以影響使用它的任何客戶機(jī)應(yīng)用程序。觸發(fā)器功能使一個(gè)過(guò)程在某個(gè)事件發(fā)生時(shí)被激活,如從表中刪除某個(gè)記錄時(shí),激活相應(yīng)的過(guò)程。例如,某個(gè)作為累計(jì)成分的記錄被刪除時(shí),應(yīng)該重新進(jìn)行累計(jì),使累計(jì)數(shù)反映最新情況。存儲(chǔ)過(guò)程語(yǔ)言已列入了MySQL準(zhǔn)備實(shí)現(xiàn)的計(jì)劃。
■ 視圖。視圖是一個(gè)邏輯概念,其功能像表但本身不是表。它提供了一種查看不同表中的列的途徑,在查看時(shí)好像這些列屬于同一個(gè)表一樣。視圖有時(shí)也稱為虛表。MySQL也準(zhǔn)備實(shí)現(xiàn)視圖功能。
■ 記錄級(jí)權(quán)限和鎖定。MySQL支持各種權(quán)限,從全局權(quán)限到數(shù)據(jù)庫(kù)、表、列的權(quán)限。但它不支持記錄級(jí)的權(quán)限。不過(guò),可在應(yīng)用程序中利用GET_LOCK( ) 和R E L E A S E _LOCK( ) 函數(shù)來(lái)實(shí)現(xiàn)協(xié)同記錄鎖。這個(gè)過(guò)程在附錄C“運(yùn)行算符和函數(shù)參考”中相應(yīng)的項(xiàng)目下介紹。
■ “- -”作為注釋的開始。MySQL不支持這種注釋風(fēng)格,因?yàn)樗且粋(gè)有歧義的結(jié)構(gòu),雖然自MySQL3.23 以來(lái),注釋可用兩個(gè)短劃線加一個(gè)空格開始。
關(guān)鍵字:MySQL、服務(wù)器、數(shù)據(jù)庫(kù)
新文章:
- CentOS7下圖形配置網(wǎng)絡(luò)的方法
- CentOS 7如何添加刪除用戶
- 如何解決centos7雙系統(tǒng)后丟失windows啟動(dòng)項(xiàng)
- CentOS單網(wǎng)卡如何批量添加不同IP段
- CentOS下iconv命令的介紹
- Centos7 SSH密鑰登陸及密碼密鑰雙重驗(yàn)證詳解
- CentOS 7.1添加刪除用戶的方法
- CentOS查找/掃描局域網(wǎng)打印機(jī)IP講解
- CentOS7使用hostapd實(shí)現(xiàn)無(wú)AP模式的詳解
- su命令不能切換root的解決方法
- 解決VMware下CentOS7網(wǎng)絡(luò)重啟出錯(cuò)
- 解決Centos7雙系統(tǒng)后丟失windows啟動(dòng)項(xiàng)
- CentOS下如何避免文件覆蓋
- CentOS7和CentOS6系統(tǒng)有什么不同呢
- Centos 6.6默認(rèn)iptable規(guī)則詳解