MyISAM 調度(優先級)的一些優化【轉】

MySQL的MyISAM引擎如今愈來愈被淡化了,可是仍是有必要再溫習總結一下的。mysql

      容許你改變語句調度的優先級,它可使來自多個客戶端的查詢更好地協做,這樣單個客戶端就不會因爲鎖定而等待很長時間。改變優先級還能夠確保特定類型的查詢被處理得更快。這一部 分講解MySQL的默認的調度策略和能夠用來影響這些策略的選項。它還談到了併發性插入操做的使用和存儲引擎鎖定層次對客戶端的併發性的影響。爲了討論的 方便,咱們把執行檢索(SELECT)的客戶端稱爲"讀取者",把執行修改操做(DELETE、INSERT、REPLACE或UPDATE)的客戶端稱 爲"寫入者"。sql

MySQL的默認的調度策略可用總結以下:
· 寫入操做優先於讀取操做。
· 對某張數據表的寫入操做某一時刻只能發生一次,寫入請求按照它們到達的次序來處理。
· 對某張數據表的多個讀取操做能夠同時地進行。

  MyISAM和MEMORY存儲引擎藉助於數據表鎖來實現這樣的調度策略。當客戶端訪問某張表的時候,首先必須獲取它的鎖。當客戶端完成對錶的 操做的時候,鎖就會被解除。經過LOCK TABLES和UNLOCK TABLES語句來顯式地獲取或釋放鎖是可行的,可是在一般狀況下,服務器的鎖管理器會自動地在須要的時候獲取鎖,在再也不須要的時候釋放鎖。獲取的鎖的類 型依賴於客戶端是寫入仍是讀取操做。

  對某張表進行寫入操做的客戶端必須擁有獨佔的(排他的)訪問權的鎖。操做在進行的過程當中,該數據表處於不一致的(inconsistent)狀 態,由於數據記錄在刪除、添加或修改的時候,數據表上的索引也可能須要更新以相互匹配。這個數據表在變化的過程當中,若是容許其它的客戶端訪問,會出現問 題。很是明顯,容許兩個客戶端同時寫入一張數據表是不利的,由於這樣的操做會很快使數據表中的信息成爲一堆無用的垃圾。可是容許客戶端讀取變化之中的數據 表也很差,由於正在讀取的位置中的數據可能正在變化(修改),讀取的結果可能不是真實的。

  對某張表執行讀取操做的客戶端必須獲取一個鎖,防止在讀取的過程當中,其它的客戶端寫入或改變表。可是這個鎖不須要獨佔的訪問權。讀取操做不會改變數據,所以沒有理由讓某個讀取者阻止其它的讀取者訪問這張表。所以讀取鎖容許其它的客戶端在同一時刻讀取這張表。

MySQL提供了幾個語句調節符,容許你修改它的調度策略:
· LOW_PRIORITY關鍵字應用於DELETE、INSERT、LOAD DATA、REPLACE和UPDATE。
· HIGH_PRIORITY關鍵字應用於SELECT和INSERT語句。
· DELAYED關鍵字應用於INSERT和REPLACE語句。服務器

LOW_PRIORITY和HIGH_PRIORITY調節符影響那些使用數據表鎖的存儲引擎(例如MyISAM和MEMORY)。DELAYED調節符做用於MyISAM和MEMORY數據表。併發

改變語句調度的優先級
   LOW_PRIORITY關鍵字影響DELETE、INSERT、LOAD DATA、REPLACE和UPDATE語句的執行調度。一般狀況下,某張數據表正在被讀取的時候,若是有寫入操做到達,那麼寫入者一直等待讀取者完成操 做(查詢開始以後就不能中斷,所以容許讀取者完成操做)。若是寫入者正在等待的時候,另外一個讀取操做到達了,該讀取操做也會被阻塞(block),由於默 認的調度策略是寫入者優先於讀取者。當第一個讀取者完成操做的時候,寫入者開始操做,而且直到該寫入者完成操做,第二個讀取者纔開始操做。

   若是寫入操做是一個LOW_PRIORITY(低優先級)請求,那麼系統就不會認爲它的優先級高於讀取操做。在這種狀況下,若是寫入者在等待的時候,第 二個讀取者到達了,那麼就容許第二個讀取者插到寫入者以前。只有在沒有其它的讀取者的時候,才容許寫入者開始操做。理論上,這種調度修改暗示着,可能存在 LOW_PRIORITY寫入操做永遠被阻塞的狀況。若是前面的讀取操做在進行的過程當中一直有其它的讀取操做到達,那麼新的請求都會插入到 LOW_PRIORITY寫入操做以前。

  SELECT查詢的HIGH_PRIORITY(高優先級)關鍵字也相似。它容許 SELECT插入正在等待的寫入操做以前,即便在正常狀況下寫入操做的優先級更高。另一種影響是,高優先級的SELECT在正常的SELECT語句以前 執行,由於這些語句會被寫入操做阻塞。

  若是你但願全部支持LOW_PRIORITY選項的語句都默認地按照低優先級來處理,那麼請使用--low-priority-updates選項來啓動服務器。經過使用INSERT HIGH_PRIORITY來把INSERT語句提升到正常的寫入優先級,能夠消除該選項對單個INSERT語句的影響高併發

使用延遲插入操做
  DELAYED調節符應用於INSERT和REPLACE語句。當 DELAYED插入操做到達的時候,服務器把數據行放入一個隊列中,並當即給客戶端返回一個狀態信息,這樣客戶端就能夠在數據表被真正地插入記錄以前繼續 進行操做了。若是讀取者從該數據表中讀取數據,隊列中的數據就會被保持着,直到沒有讀取者爲止。接着服務器開始插入延遲數據行(delayed-row) 隊列中的數據行。在插入操做的同時,服務器還要檢查是否有新的讀取請求到達和等待。若是有,延遲數據行隊列就被掛起,容許讀取者繼續操做。當沒有讀取者的 時候,服務器再次開始插入延遲的數據行。這個過程一直進行,直到隊列空了爲止。

  感受上LOW_PRIORITY和DELAYED是相 似的,二者都容許數據行插入操做被延遲,可是它們對客戶端操做的影響卻有很大的差別。LOW_ PRIORITY強迫客戶端等待,直到那些數據行能夠被插入數據表。DELAYED容許客戶端繼續操做,服務器在內存中緩衝那些數據行,直到本身有時間處 理它們。

  若是其它的客戶端可能運行很長的SELECT語句而且你不但願阻塞,等待插入操做完成的時候,INSERT DELAYED就很是有用處了。客戶端提交INSERT DELAYED的時候可能處理得很快,由於服務器只是簡單地把要插入的數據行排隊。

   可是,你也必須知道正常的INSERT與INSERT DELAYED行爲之間的一些其它的差別。若是INSERT DELAYED語句包含語法錯誤,客戶端會獲得一個錯誤,可是卻沒法獲得其它一些在正常狀況下可使用的信息。例如,當語句返回的時候,你沒法依賴(得 到)AUTO_INCREMENT(自動增加)值。一樣,你沒法獲得惟一索引的副本數量。發生這種狀況的緣由在於插入操做在真正地被執行以前已經返回了狀 態信息。另外一種可能出現的狀況是,因爲INSERT DELAYED語句的數據行都在內存中排隊,當服務器崩潰或者使用kill -9退出的時候,數據行可能丟失(正常狀況下,kill -TERM終止命令不會致使這種狀況,由於服務器在退出以前會把數據行插入表中)。性能

使用併發的插入操做
   MyISAM存儲引擎有一條例外的規則,它容許讀取者阻塞寫入者。這種現象發生在MyISAM數據表中間沒有"空洞"(多是刪除或更新數據行的結果) 的狀況下。當數據表沒有"空洞"的時候,任何INSERT語句必然在末尾而不是中部添加數據行。在這種狀況下,MySQL容許其它客戶端在讀取數據的同時 向數據表添加數據行。這就是"併發性插入操做",由於它們同時發生,檢索並無被阻塞。

      若是你但願使用併發性插入操做,請注意下面一些事項:
· 在INSERT語句中不要使用LOW_PRIORITY調節符。它會引發INSERT常常被讀取者阻塞,所以阻礙了併發性插入操做的執行。
· 若是讀取者須要顯式地鎖定數據表以執行併發性插入操做,就應該使用LOCK TABLES ... READ LOCAL,而不是LOCK TABLES ... READ。LOCAL關鍵字會獲取一個鎖,容許併發性操做繼續進行,由於它只能應用於數據表中已有的數據行,不會阻塞那些添加到末尾的新數據行。
· LOAD DATA操做應該使用CONCURRENT調節符,容許該數據表上的SELECT語句同時執行。
· 中間包含了"空洞"的MyISAM數據表不能使用併發性插入操做。可是,你可使用OPTIMIZE TABLE語句來整理該數據表的碎片。----concurrent_insert:0,1,2spa

鎖的層次和併發性
  前面討論的調度調節符容許你改變默認的調度策略。其中的大部份內容都是介紹使用這些調節符來解決數據表層次(table-level)的鎖引發的問題,這都是MyISAM和MEMORY存儲引擎用來管理數據表爭用的問題的。
   BDB和InnoDB存儲引擎實現了不一樣層次的鎖,因此其性能特徵和對爭用的管理是不一樣的。BDB引擎使用頁面層次(page-level)的鎖。 InnoDB引擎使用數據行層次(row-level)的鎖,可是隻在必要的時候使用(在不少狀況下,例如當讀取操做都完成的時候,InnoDB可能根本 就不使用鎖)。

  存儲引擎使用的鎖的層次對客戶端的併發操做有很大的影響。假設兩個客戶端都但願更新某個數據表中的一行。因爲要執行更新,每一個客戶端都須要一個寫入鎖。對於MyISAM數據表,引擎會爲第一個客戶端分配一個鎖,這會引發第二個客戶端阻塞,直到第一個客戶端完成操做。對於 BDB數據表,它能夠實現更大的併發性:兩個更新操做會同步進行,除非兩個數據行都位於同一個頁面中。在InnoDB數據表中,併發性更高;只要兩個客戶 端沒有更新同一行,兩個更新操做就能同時發生。索引

      通常的規則是,鎖的層次越細微,併發性越好,由於只要客戶端使用數據表的部分不一樣,那麼使用表的客戶端就能夠更多。
· MyISAM檢索的速度很是快。可是使用表層次的鎖可能成爲混合的檢索和更新環境中的問題,特別是檢索傾向於長時間運行的時候。在這些條件下,更新可能須要等待好久才能進行。
· 當更新操做不少的時候,BDB和InnoDB數據表能夠提供更好的性能。因爲鎖在頁面或數據行層次進行,表被鎖定的範圍較小。這會減小鎖的爭用,提升併發性。隊列

      在防止死鎖(deadlock)方面,表鎖比行鎖更有優點。使用表鎖的時候,死鎖不會發生。由於服務器能夠經過查看語句來檢測須要的數據表,並提早鎖定它們。而InnoDB會發生死鎖,由於存儲引擎沒有在事務開始的時候分配全部必要的鎖。而是在事務處理的過程當中,當檢測到須要鎖的時候才分配。這就可能出現兩個語句獲取了鎖,接着試圖進一步獲取鎖(須要多個鎖),可是這些鎖卻被對方保持着,等待對方釋放。其結果是每一個客戶端都擁有一個鎖,同時還須要利用其它的客戶端擁有的鎖才能繼續執行。這會致使死鎖,服務器必須終止其中一個事務。事務


使用方法:

優先操做 HIGH_PRIORITY
HIGH_PRIORITY可使用在select和insert操做中,讓MYSQL知道,這個操做優先進行。
SELECT HIGH_PRIORITY * FROM TABLE1;

滯後操做 LOW_PRIORITY
LOW_PRIORITY可使用在insert和update操做中,讓mysql知道,這個操做滯後。
update LOW_PRIORITY table1 set field1= where field1= …

延時插入 INSERT DELAYED
INSERT DELAYED INTO table1 set field1= …
INSERT DELAYED INTO 是客戶端提交數據給MySQL,MySQL返回OK狀態給客戶端。而這是並非已經將數據插入表,而是存儲在內存裏面等待排隊。當mysql有空餘時,再插入。另外一個重要的好處是,來自許多客戶端的插入被集中在一塊兒,並被編寫入一個塊。這比執行許多獨立的插入要快不少。壞處是,不能返回自動遞增 的ID,以及系統崩潰時,MySQL尚未來得及插入數據的話,這些數據將會丟失。

相關文章
相關標籤/搜索