MySQL併發控制之讀寫鎖和鎖粒度詳解

2021-10-07 20:19:32 字數 2287 閱讀 8023

**無論何時,只要有多個查詢需要在同一時刻修改資料,都會產生併發控制的問題。本章的目的是討論mysql在兩個層面的併發控制:**伺服器層與儲存引擎層。併發控制是 乙個內容龐大的話題,有大量的理**獻對其進行過詳細的論述。本章只簡要地討論 mysql如何控制併發讀寫,因此讀者需要有相關的知識來理解本章接下來的內容。

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

但如果兩個程序在同一時刻對同乙個郵箱投遞郵件,會發生什麼情況?顯然,郵箱的數這種鎖的方案在實際應用環境中雖然工作良好,但並不支援併發處理。因為在任意乙個 時刻,只有乙個程序可以修改郵箱的資料,這在大容量的郵箱系統中是個問題。

1.2.1讀寫鎖

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

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

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

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

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

1.2.2鎖粒度

一種提高共享資源併發性的方式就是讓鎖定物件更有選擇性。盡量只鎖定需要修改的部 ex> 分資料,而不是所有的資源。更理想的方式是,只對會修改的資料片進行精確的鎖定。

任何時候,在給定的資源上,鎖定的資料量越少,則系統的併發程度越高,只要相互之 間不發生衝突即可。

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

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

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

表鎖(table lock) 表鎖是mysql中最基本的鎖策略,並且是開銷最小的策略。表鎖非常類似於前文描述 的郵箱加鎖機制:它會鎖定整張表。乙個使用者在對錶進行寫操作(插入、刪除、更新等) 前,需要先獲得寫鎖,這會阻塞其他使用者對該錶的所有讀寫操作。只有沒有寫鎖時,其 他讀取的使用者才能獲得讀鎖,讀鎖之間是不相互阻塞的。 在特定的場景中,表鎖也可能有良好的效能。例如,read local表鎖支援某些型別的並 發寫操作。另外,寫鎖也比讀鎖有更高的優先順序,因此乙個寫鎖請求可能會被插入到讀 鎖佇列的前面(寫鎖可以插入到鎖佇列中讀鎖的前面,反之讀鎖則不能插入到寫鎖的前 面)。 儘管儲存引擎可以管理自己的鎖,mysql本身還是會使用各種有效的表鎖來實現不同 的目的。例如,伺服器會為諸如alter table之類的語句使用表鎖,而忽略儲存引擎的 鎖機制。

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

鎖php mysql 的讀寫鎖與併發控制

1.無論何時只要有多個查詢在同一時刻修改資料,都會產生併發控制的問題 2.討論mysql在兩個層面,伺服器層和儲存引擎層,如何併發控制讀寫 3.舉了個mbox郵箱檔案的例子,說如果有多個程序同時對mbox檔案寫東西,那麼在檔案的末尾會,交叉混亂的新增,比如程序1寫了幾行,程序2也寫了幾行,互相交叉,...

Java併發之讀 寫鎖

讀取 沒有執行緒正在做寫操作且沒有執行緒請求寫操作 寫入 沒有執行緒正在做寫操作 這裡假設寫操作的優先順序比讀操作高 當乙個執行緒已經擁有寫鎖,才允許寫鎖重入 public class readwritelock writerequest writeaccesses writingthread ca...

MySQL mysql 的讀寫鎖與併發控制

1.無論何時只要有多個查詢在同一時刻修改資料,都會產生併發控制的問題 2.討論mysql在兩個層面,伺服器層和儲存引擎層,如何併發控制讀寫 3.舉了個mbox郵箱檔案的例子,說如果有多個程序同時對mbox檔案寫東西,那麼在檔案的末尾會,交叉混亂的新增,比如程序1寫了幾行,程序2也寫了幾行,互相交叉,...