MySQL 併發控制

2021-12-30 12:28:50 字數 2499 閱讀 3717

【mysql】併發控制。無論何時,只有有多個查詢需要在同一時刻修改資料,都會產生併發控制的問題。這裡討論mysql在兩個層面的併發控制:伺服器層與儲存引擎層。併發控制是乙個內容龐大的話題,有大量的理**獻對其進行詳細的論述。在此只是簡要地討論mysql如何控制併發讀寫。

以unix系統的email box為例子,典型的mbox檔案格式是非常簡單的。乙個mbox郵箱中的所有郵件都序列在一起,彼此首尾相連。這種格式對於讀取和肥西郵件資訊非常友好,同時投遞郵件也很容易,只要在檔案末尾附加新的郵件內容即可。

但是如果兩個程序在同一時刻對同乙個郵箱投遞郵件,會發生什麼情況?顯然,郵箱的資料會被破壞,兩封郵件的內容會交叉地附加在郵箱檔案的末尾。設計娘好的郵箱投遞系統會通過鎖(lock)來防止資料損壞。如果客戶試圖投遞郵件,而郵箱已經被其他客戶鎖住,那麼就必須等待,直到鎖釋放才能進行投遞。

這種鎖的方案在實際應用環境中雖然工作良好,但是並不支援併發處理。因為在任意乙個時刻,只有乙個程序可以修改郵箱的資料,這在大容量的郵箱系統中是個問題。

從郵箱中讀取資料沒有這樣的麻煩,即使同一時刻多個使用者併發讀取也不會有什麼問題。因為讀取不會修改資料,所以不會出錯。但是如果某個客戶正在讀取郵箱,同時另乙個使用者試圖刪除編號為25的郵件,會產生什麼結果?結論是不確定的,讀的客戶可能會報錯退出,也可能讀取不到一致的郵箱資料。所以,為了安全起見,即使是讀取郵箱也需要特別注意。

如果把上述的郵箱當成資料庫中的一張表,把郵件當成表中的一行記錄,就很容易看出,同樣的問題依然存在。從很多方面來說,郵箱就是一張簡單的資料庫表。修改資料庫表中的記錄,和刪除或者修改郵箱中的郵件資訊,十分類似。

解決這類經典的問題的方法就是併發控制(讀鎖和寫鎖)。其實非常簡單,在處理併發讀或者寫的時候,可以通過實現乙個由兩種型別的鎖組成鎖系統來解決問題。這兩種型別的鎖通常被稱為共享鎖(shared lock)排他鎖(exclusive lock),也叫讀鎖(read lock)寫鎖(write lock)

這裡先不討論如何具體實現,描述一下鎖的概念如下:讀鎖是共享的,或者說是相互不阻塞的。多個客戶在同一時刻可以同時讀取同一資源,而互不干擾。寫鎖則是排他的,也就是說乙個寫鎖會阻塞其他的寫鎖和讀鎖,這是出於安全策略的考慮,只有這樣,才能確保給定的時間裡,只有乙個使用者能執行寫入,並防止其他使用者讀取正在寫入的同一資源。

在實際的資料庫系統中,每時每刻都在發生鎖定,當某個使用者在修改某一部分資料的時候,mysql會通過鎖定防止其他使用者讀取同一資料。大多數時候,mysql鎖的內部管理都是透明的。

一種提供共享資源併發性的方式就是讓鎖定物件更有選擇性。盡量只鎖定需要修改的部分資料,而不是所有的資源。更理想的方式是,只對會修改的資料片(具體到鎖定所修改的字段)進行精確的鎖定。任何時候,在給定的資源上,鎖定的資料量越少,則系統的併發成都越高,只要互相之間不發生衝突即可。

問題是加鎖也需要消耗資源。鎖的各種操作,包括獲得鎖,檢查鎖是否已經被解除,釋放鎖等,都會增加系統的開銷。如果系統花費大量的時間來管理鎖,而不是訪問資料,那麼系統的效能可能因此受到影響。

所謂的鎖策略,就是在鎖的開銷和資料的安全性之間尋求平衡,這種平衡當然有會影響到效能,大多數商業資料庫系統沒有提供更多的選擇,一般都是在表上施加行級鎖(row-level lock),並以各種複雜的方式來實現,以便在鎖比較多的情況下盡可能地提供更好的效能。

而mysql則提供多種選擇,每種mysql儲存引擎都可以實現自己的鎖策略和鎖粒度。在儲存引擎的設計中,鎖管理是個非常重要的決定。將鎖粒度固定在某個級別,可以為某些特定的應用場景提供更好的效能。但是同事卻會失去對另外一些應用場景的良好支援。好在mysql支援多個儲存引擎的架構,所以不需要單一的通用解決方案。下面介紹兩種最重要的鎖策略。

表鎖是mysql中最基本的鎖策略,並且是開銷最小的策略。表鎖非常類似於前文描述的郵箱加鎖機制:它會鎖定整張表。乙個使用者在對錶進行寫操作(插入,刪除,更新等等)前,需要先獲得寫鎖,這個會阻塞其他使用者對該錶的所有讀寫操作。只有沒有寫鎖的時候,其他讀取的使用者才能獲得讀鎖,讀鎖之間是不互相阻塞的。

在特定的場景中,表鎖也可能有良好的效能。例如,read local表鎖支援某些型別的併發寫操作。另外,寫鎖也比讀鎖有更高的優先順序,因此乙個寫鎖請求可能會被插入到讀鎖佇列的前面(寫鎖可以插入到鎖佇列中讀鎖的前面,反之讀鎖則不能插入寫鎖的前面)。

儘管儲存引擎可以管理自己的鎖,mysql本身還是會使用各種有效的表鎖來實現不同的目的。例如伺服器會諸如alter table之類的語句使用表鎖,而忽略儲存引擎的鎖機制。

【備註:鎖機制是儲存引擎管理的,但是mysql本身也會有時候強制管理這個鎖機制】

行級鎖可以最大程度地支援併發處理(同時也帶來了最大的鎖開銷)。眾多周知,在innodb和xtradb,以及其他一些儲存引擎中實現了行級鎖。行級鎖只在儲存引擎層實現,而mysql伺服器層(如果有必要,請回顧上篇的邏輯架構圖)沒有實現。伺服器層完全不了解儲存引擎中的鎖實現。在本章的後續內容以及全書中,所有的儲存引擎都以自己的方式顯示了鎖機制

mysql 併發控制 mysql併發控制

mysql併發控制 當有多個查詢需要同時修改同乙個資料,就會產生併發控制的問題。mysql可以在兩個層面進行併發控制 伺服器層和儲存引擎層。mysql通過加鎖實現併發控制 鎖有兩類 讀鎖 共享鎖,即乙個讀鎖不會阻塞其它讀鎖,多個使用者可同時讀取同乙個資源,而不互相干擾。寫鎖 排他鎖,即乙個寫鎖會阻塞...

mysql 併發控制

1 多個執行緒同時修改資料,存在資料不一致的情況,也就是併發控制的問題。2 mysql提供讀鎖和寫鎖,讀鎖之上可以再加讀鎖,不能加寫鎖,而寫鎖之上不能加任何鎖。也就是說,讀鎖是共享的,寫鎖是排他的。3 鎖粒度,為了更好的併發控制,鎖的粒度應該盡可能小,也就是只鎖定修改的資料。但是,鎖本身也有一定的開...

mysql併發控制

mysql併發控制 當有多個查詢需要同時修改同乙個資料,就會產生併發控制的問題。mysql可以在兩個層面進行併發控制 伺服器層和儲存引擎層。mysql通過加鎖實現併發控制 鎖有兩類 讀鎖 共享鎖,即乙個讀鎖不會阻塞其它讀鎖,多個使用者可同時讀取同乙個資源,而不互相干擾。寫鎖 排他鎖,即乙個寫鎖會阻塞...