程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> 關於MYSQL數據庫 >> MySQL不支持的功能

MySQL不支持的功能

編輯:關於MYSQL數據庫

    3.9 MySQL不支持的功能

    本節介紹其他數據庫中有而MySQL中無的功能。它介紹省略了什麼功能,以及在需要這些功能時怎麼辦。一般情況下, MySQL之所以忽略某些功能是因為它們有負面性能影響。有的功能正在開發者的計劃清單上,一旦找到一種方法可以實現相應的功能而又不致於影響良好性能的目標,就會對它們進行實現。

    ■ 子選擇。子選擇是嵌套在另一個SELECT 語句內的SELECT 語句,如下面的查詢所示:

    SELECT * FROM score

    WHERE event_id IN (SELECT event_id FROM event WHERE type = "T")

    子選擇打算在MySQL3.24 中給出,到那時它們就不會忽略了。但到那時,許多用子選擇撰寫的查詢也可以用連接來編寫。請參閱3 . 8 . 1節“將子選擇編寫為連接”。

    ■ 事務處理和提交/回退。事務處理是由其他客戶機作為一個整體不中斷執行的一組SQL語句。提交/回退功能允許規定數條語句作為一個整體執行或不執行。即,如果事務處理中的任何一條語句失敗,那麼直到該語句前執行的所有語句的作用都被撤消。
ySQL 自動進行單一SQL 語句的同步以免客戶機互相干擾。(例如,兩個客戶機不能對相同的表進行同時寫入。)此外,可利用LOCK TABLES 和UNLOCK TABLES將數條語句組成一個整體,這使您能夠完成單條語句的並發控制所不能滿足的操作。MySQL與事務處理有關的問題是,它不能自動對數條語句進行組織,而且如果這些語句中有某一條失敗後也不能對它們進行回退。

    為了弄清事務處理為什麼有用,可舉例說明。假如您在服裝銷售業工作,無論何時,只要您的銷售人員進行了一次銷售,都要更新庫存數目。下面的例子說明了在多個銷售人員同時更新數據庫時可能出現的問題(假如初始的襯衫庫存數目為4 7):

    t1銷售人員1賣出3件襯衫

    t2 銷售人員檢索當前襯衫計數( 4 7):

    SELECT quantity FROM inventory WHERE item = "shirt"

    t3 銷售人員2賣出2件襯衫

    t4 銷售人員2檢索當前襯衫計數( 4 7)

    SELECT quantity FROM inventory WHERE item = "shirt"

    t5 銷售人員1計算庫存的新數目為47 - 3 = 44 並設置襯衫計數為44:

    UPDATE inventory SET quantity = 44 WHERE item = "shirt"

    t6 銷售人員2計算庫存的新數目為47 - 2 = 45 並設置襯衫計數為45:

    UPDATE inventory SET quantity = 45 WHERE item = "shirt"

    在這個事件序列結束時,您已經賣掉了5 件襯衫,但庫存數目卻是45 而不是4 2。問題是如果在一條語句中查看庫存而在另一條語句中更新其值,這是一個多語句的事務處理。第二條語句中所進行的活動取決於第一條語句中檢索出的值。但是如果在重疊的時間范圍內出現獨立的事務處理,則每個事務處理的語句會糾纏在一起,並且互相干擾。在事務處理型的數據庫中,每個銷售人員的語句可作為一個事務處理執行,這樣,銷售人員2 的語句在銷售人員1的語句完成之前不會被執行。在MySQL中,可用兩種方法達到這個目的:

   ■ 方法1:作為一個整體執行一組語句。可利用LOCK TABLES 和UNLOCK TABLES將語句組織在一起,並將它們作為一個原子單元執行:鎖住所需使用的表,發布查詢,然後釋放這些鎖。這樣阻止了其他人在您鎖住這些表時使用它們。利用表同步,庫存情況如下所示:

    t1銷售人員1賣出3件襯衫

    t2 銷售人員1請求一個鎖並檢索當前襯衫計數(47)

    LOCK TABLES inventory WRITE

    SELECT quantity FROM inventory WHERE item = "shirt"

    t3 銷售人員2賣出2件襯衫

    t4 銷售人員2試圖取得一個鎖:這被阻塞,因為銷售人員1已經占住了鎖:

    LOCK TABLES inventory WRITE

    t5 銷售人員1計算庫存的新數目為47 - 3 = 44 並設置襯衫計數為44,然後釋放鎖:

    UPDATE inventory SET quantity = 44 WHERE item = "shirt"

    UNLOCK TABLES

    t6 現在銷售人員2的鎖請求成功。銷售人員2檢索當前襯衫計數( 44)

    SELECT quantity FROM inventory WHERE item = "shirt"

    t7 銷售人員2計算庫存的新數目為44 - 2 = 42,設置襯衫計數為4 2,然後釋放鎖:

    UPDATE inventory SET quantity = 42 WHERE item = "shirt"

    UNLOCK TABLES

    現在來自兩個事務處理的語句不混淆了,並且庫存襯衫數也正確進行了設置。我們在這裡使用了一個WRITE 鎖,因為我們需要修改inventory 表。如果只是讀取表,可使用READ 鎖。當您正在使用表時,這個鎖允許其他客戶機讀取表。在剛才舉的例子中,銷售人員2大概不會注意到執行速度上的差異,因為其中的事務處理都很短,執行速度很快。但是,作為一個具有普遍意義的規則,那就是應該盡量避免長時間地鎖住表。

    如果您正在使用多個表,那麼在您執行成組查詢之前,必須鎖住他們。如果只是從某個特定的表中讀取數據,那麼只需給該表加一個讀出鎖而不是寫入鎖。假如有一組查詢,其中想對inventory 表作某些更改,而同時需要從customer 表中讀取某些數據。在此情形下,inventory 表上需要一個寫入鎖,而customer 表上需要一個讀出鎖:

    LOCK TABLES inventory WRITE,customer READ
    ...
    UNLOCK TABLES

    這裡要求您自己對表進行加鎖和解鎖。支持事務處理的數據庫系統將會自動完成這些工作。但是,在作為一個整體執行的分組語句方面,無論在是否支持事務處理的數據庫中都是相同的。

    ■ 方法2:使用相對更新而不是絕對更新。要解決來自多個事務處理的語句混淆問題,應消除語句之間的依賴性。雖然這樣做並不都總是可能的,它只針對我們的庫存例子可行。對於方法1中所用的庫存更新方法,其中事務處理需要查看當前庫存數目,並依據銷售襯衫的數目計算新值,然後更新襯衫的數目。有可能通過相對於當前襯衫數目進行計數更新,在一個步驟中完成工作。如下所示:

    t1銷售人員1賣出3件襯衫

    t2 銷售人員1將襯衫計數減3:

    UPDATE inventory SET quantity = quantity - 3 WHERE item = "shirt"

    t3 銷售人員2賣出2件襯衫

    t4 銷售人員2將襯衫計數減2:

    UPDATE inventory SET quantity = quantity - 2 WHERE item = "shirt"

    因此,這裡根本不需要多條語句的事務處理,從而也不需要鎖住表以模擬事務處理功能。如果所使用的事務處理類型與這裡類似,那麼就可以不用事務處理也能完成工作。上面的例子說明了在特殊情形下怎樣避免對事務處理功能的需求。但這並不是說不存在那種確實需要事務處理功能的場合。典型的例子是財務轉賬,其中錢從一個賬戶轉到另一個賬戶。假如Bill 給Bob 開了一張$100 的支票,Bob 兌現了這張支票。Bill 的戶頭上應該減掉$100 而Bob 的戶頭上應該增加相同數量的錢:

    UPDATE account SET balance = balance -100 WHERE name = "Bill"

    UPDATE account SET balance = balance +100 WHERE name = "Bob"

    如果在這兩條語句執行中,系統發生了崩潰,此事務處理就不完整了。具有真正事務處理和提交/回退功能的數據庫系統能夠處理這種情況(至少從理論上能夠處理。您可能仍然必須判斷遇到了哪些事務處理並重新發布它們,但至少不會擔心事務只處理了一半)。在MySQL中,系統崩潰時可通過檢查更新日志來判斷事務處理的狀態,雖然這可能需要對日志進行某種手工檢查。

    ■ 外部鍵和引用完整性。外部鍵允許定義一個表中的鍵與另一個表中的鍵相關,而引用完整性允許放置對包含外部鍵的表可以做什麼的約束。例如, samp_db 樣例數據庫的score 表中包含一個student_id 列,我們用它來將學分記錄關聯到student 表中的學生。score.student_id 將定義為支持此概念的數據庫中的一個外部鍵,我們將在其上加上一條約束,使不能為student 表中不存在的學生輸入學分記錄。此外,應該允許級聯刪除,以便如果某個學生從student 表中被刪除後,該學生的任何學分記錄將會自動地從score 表中刪除。

    外部鍵有助於保持數據的一致性,而且還提供了某種方便的手段。MySQL不支持外部鍵的原因主要是由於它對數據庫的實現與維護有負作用。(MySQL參考指南詳細列出了這些原因。)注意,對於外部鍵的這種看法與其他數據庫文獻中的看法有些不同,有的數據庫文獻通常將它們描述成“基本的”。MySQL的開發者並不贊同這個觀點。如果您贊成,那麼最好是考慮采用其他提供外部鍵支持的數據庫。如果數據具有特別復雜的關系,您可能不希望擔負在應用程序中實現這些相關性的工作。(即使這樣做的工作量要比增加幾個額外的DELETE 語句的工作量要稍少一些。)除了在一定程度上能夠在CREATE TABLE 語句中分析FOREIGN KEY 子句外,MySQL不支持外部鍵。(這有助於使從其他數據庫移植代碼到MySQL更為容易。)MySQL不強制讓外部鍵作為一種約束,也不提供級聯刪除功能。

    外部鍵強制實施的約束一般不難用程序邏輯來實現。有時,它只是一個怎樣進行數據錄入處理的問題。例如,為了將一個新記錄插入score 表,不太可能插入不存在的學生的學分。顯然,輸入一組學分的方法應該是根據從student 表得出的學生名單,對每個學生,取其學分並利用該學生的ID 號產生一個score 表的記錄。對於這個過程,不存在錄入一個不存在的學生的記錄的可能。您不會憑空造出一個學分記錄來插入score 表。要實現DELETE 的級聯效果,必須用自己的應用程序邏輯來完成。假如想要刪除13 號學生。這也隱含表示需要刪除該學生的學分記錄。在支持級聯刪除的數據庫中,只需要用如下的語句就可以刪除student 表的記錄和相應的score 表的記錄:

    DELETE FROM student WHERE student_id = 13

    而在MySQL中,必須明確地用DELETE 語句自己進行第二個刪除語句:

    DELETE FROM student WHERE student_id = 13

    DELETE FROM score WHERE student_id = 13

    ■ 存儲過程和觸發器。存儲過程是編譯和存放在服務器中的SQL 代碼。它可在以後調用而無需從客戶機發送並分析。可以對一個過程進行更改以影響使用它的任何客戶機應用程序。觸發器功能使一個過程在某個事件發生時被激活,如從表中刪除某個記錄時,激活相應的過程。例如,某個作為累計成分的記錄被刪除時,應該重新進行累計,使累計數反映最新情況。存儲過程語言已列入了MySQL准備實現的計劃。

    ■ 視圖。視圖是一個邏輯概念,其功能像表但本身不是表。它提供了一種查看不同表中的列的途徑,在查看時好像這些列屬於同一個表一樣。視圖有時也稱為虛表。MySQL也准備實現視圖功能。

    ■ 記錄級權限和鎖定。MySQL支持各種權限,從全局權限到數據庫、表、列的權限。但它不支持記錄級的權限。不過,可在應用程序中利用GET_LOCK( ) 和R E L E A S E _LOCK( ) 函數來實現協同記錄鎖。這個過程在附錄C“運行算符和函數參考”中相應的項目下介紹。

    ■ “- -”作為注釋的開始。MySQL不支持這種注釋風格,因為它是一個有歧義的結構,雖然自MySQL3.23 以來,注釋可用兩個短劃線加一個空格開始。更詳細的信息,請參閱3 . 7節“加注釋”。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved