MySQL資料庫之併發控制

2021-10-05 19:52:05 字數 2228 閱讀 7530

無論何時,只要有多個查詢需要在同一時刻修改資料,都會產生併發控制的問題。本章的目的是討論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之類的語句使用表鎖,而忽略儲存引擎的鎖機制。

行級鎖可以最大程度地支援併發處理(同時也帶來了最大的所開銷)。眾所周知,在innodb和xtradb,以及其他一些儲存引擎中實現了行級鎖。行級鎖只在儲存引擎層實現,而mysql伺服器層沒有實現。伺服器層完全不了解儲存引擎中的鎖實現。

mysql併發控制之資料庫鎖

1.mysql和redis的區別 mysql是一種關係型資料庫,資料會最終儲存在磁碟上。而redis是一種非關係型的nosql資料庫,以key value的形式儲存資料,將資料儲存在記憶體。從效能上來說,redis將資料儲存在記憶體,性 能肯定要優於mysql資料庫。但是從安全的角度來說,mysql...

資料庫之併發控制排程

序列 兩個事務分別執行,假設兩個事務t1和t2,分別的執行過程為 t1,t2 或 t2,t1 即先執行完t1再執行t2,或先執行t2再執行t1,事務的中間操作沒有交叉。可序列化 兩個事務執行的結果和事務序列執行的結果相同,注意,這裡更側重的是結果相同。衝突 每個事務可簡化為一組針對資料庫物件的rea...

資料庫併發控制

資料庫併發控制 1 在資料庫中為什麼要併發控制?答 資料庫是共享資源,通常有許多個事務同時在執行。當多個事務併發地訪問資料庫時就會產生同時讀取和 或修改同一資料的情況。若對併發操作不加控制就可能會訪問和儲存不正確的資料,破壞資料庫的一致性。所以資料庫管理系統必須提供併發控制機制。2 併發操作可能會產...