關於mysql鎖機制原理的詳細講解(一)
锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的 计算资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一 个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。本章我们着重讨论MySQL锁机制 的特点,常见的锁问题,以及解决MySQL锁问题的一些方法或建议。
Mysql用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。这些锁统称为悲观锁(Pessimistic Lock)。
MySQL锁概述
相对其他数据库而言,MySQL的锁机制比较简单,其最 显著的特点是不同的存储引擎支持不同的锁机制。比如,MyISAM
和MEMORY
存储引擎采用的是表级锁(table-level locking
);BDB
存储引擎采用的是页面锁(page-level locking
),但也支持表级锁;InnoDB
存储引擎既支持行级锁(row-level locking
),也支持表级锁,但默认情况下是采用行级锁。
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
从上述特点可见,很难笼统地说哪种锁更好,只能就具体应用的特点来说哪种锁更合适!仅从锁的角度 来说:表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用;而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有 并发查询的应用,如一些在线事务处理(OLTP)系统。
MyISAM表锁
MySQL的表级锁有两种模式:表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)。
对MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;对 MyISAM表的写操作,则会阻塞其他用户对同一表的读和写操作;MyISAM表的读操作与写操作之间,以及写操作之间是串行的!根据如表20-2所示的 例子可以知道,当一个线程获得对一个表的写锁后,只有持有锁的线程可以对表进行更新操作。其他线程的读、写操作都会等待,直到锁被释放为止。
MyISAM存储引擎的写锁阻塞读例子:
当一个线程获得对一个表的写锁后,只有持有锁的线程可以对表进行更新操作。其他线程的读、写操作都会等待,直到锁被释放为止。
MyISAM存储引擎的读锁阻塞写例子:
一个session使用LOCK TABLE命令给表film_text加了读锁,这个session可以查询锁定表中的记录,但更新或访问其他表都会提示错误;同时,另外一个session可以查询表中的记录,但更新就会出现锁等待。
如何加表锁
MyISAM在執行查詢語句(SELECT)前,會自動為涉及的所有表加讀鎖,在執行更新操作(UPDATE、DELETE、INSERT等)前,會自動為涉及的表加寫鎖,這個過程並不需要使用者乾預,因此,使用者一般不需要直接用LOCK TABLE指令來為MyISAM表明確加鎖。在範例中,顯式加鎖基本上都是為了演示而已,並非必須如此。
給MyISAM表顯示加鎖,一般是為了在一定程度模擬事務操作,實現對某一時間點多個表的一致性讀取。例如, 有一個訂單表orders,記錄有各訂單的總金額total,同時還有一個訂單明細表order_detail,其中記錄有各訂單每一產品的金額小計subtotal,假設我們需要檢查這兩個表的金額合計是否相符,可能就需要執行以下兩個SQL:
Select sum(total) from orders; Select sum(subtotal) from order_detail;
這時,如果不先給兩個表加鎖,就可能產生錯誤的結果,因為第一條語句執行過程中, order_detail表可能已經發生了改變。因此,正確的方法應該是:
Lock tables orders read local, order_detail read local; Select sum(total) from orders; Select sum(subtotal) from order_detail; Unlock tables;
要特別說明以下兩點內容:
1、上面的例子在LOCK TABLES時加了「local」選項,其作用就是在滿足MyISAM表並發插入條件的情況下,允許其他使用者在表尾並發插入記錄,有關MyISAM表的並發插入問題,在後面還會進一步介紹。
2、在用LOCK TABLES為表明確加表鎖時,必須同時取得所有涉及到表的鎖,且MySQL不支援鎖定升級。也就是說,在執行LOCK TABLES後,只能存取明確加鎖的這些表,不能存取未加鎖的表;同時,如果加的是讀鎖,那麼只能執行查詢操作,而不能執行更新操作。其實,在自動加鎖的 情況下也基本如此,MyISAM總是一次獲得SQL語句所需的全部鎖。這也正是MyISAM表不會出現死鎖(Deadlock Free)的原因。
當使用LOCK TABLES時,不僅需要一次鎖定用到的所有表,而且,同一個表在SQL語句中出現多少次,就要透過與SQL語句中相同的別名鎖定多少次,否則也會出錯!舉例說明如下。
(1)對actor表獲得讀鎖:
mysql> lock table actor read; Query OK, 0 rows affected (0.00 sec)
(2)但是透過別名存取會提示錯誤:
mysql> select a.first_name,a.last_name,b.first_name,b.last_name from actor a,actor b where a.first_name = b.first_name and a.first_name = 'Lisa' and a.last_name = 'Tom' and a.last_name <> b.last_name; ERROR 1100 (HY000): Table ‘a’ was not locked with LOCK TABLES
(3)需要對別名分別鎖定:
mysql> lock table actor as a read,actor as b read; Query OK, 0 rows affected (0.00 sec)
(4)依照別名的查詢可以正確執行:
mysql> select a.first_name,a.last_name,b.first_name,b.last_name from actor a,actor b where a.first_name = b.first_name and a.first_name = 'Lisa' and a.last_name = 'Tom' and a.last_name <> b.last_name; +————+———–+————+———–+ | first_name | last_name | first_name | last_name | +————+———–+————+———–+ | Lisa | Tom | LISA | MONROE | +————+———–+————+———–+ 1 row in set (0.00 sec)
#查詢表級鎖定爭用情況
可以透過檢查table_locks_waited和table_locks_immediate狀態變數來分析系統上的表格鎖定爭奪:
mysql> show status like 'table%'; 1Variable_name | Value Table_locks_immediate | 2979 Table_locks_waited | 0 2 rows in set (0.00 sec))
如果Table_locks_waited的值比較高,則表示存在較嚴重的表級鎖定爭用情況。
並發插入(Concurrent Inserts)
當concurrent_insert設定為0時,不允許並發插入。當concurrent_insert設定為1時,如果MyISAM表中沒有空洞(即表的中間沒有被刪除的行),MyISAM允許在一個進程讀表的同時,另一個進程從表尾插入記錄。這也是MySQL的預設值。當concurrent_insert設定為2時,無論MyISAM表中有沒有空洞,都允許在表尾並發插入記錄。
在下面的例子中,session_1得到了一個表的READ LOCAL鎖,該線程可以對錶進行查詢操作,但不能對錶進行更新操作;其他的線程(session_2),雖然不能對錶進行刪除和更新操作,但卻可以對該表進行並發插入操作,這裡假設該表中間不存在空洞。
MyISAM儲存引擎的讀寫(INSERT)並發範例:
#可以利用MyISAM儲存引擎的並發插入特性,來解決應用程式中對相同表查詢和插入的鎖爭用。例如,將concurrent_insert系統變數設為2,總是允許並發插入;同時,透過定期在系統空閒時段執行 OPTIMIZE TABLE語句來整理空間碎片,收回因刪除記錄而產生的中間空洞。
MyISAM的鎖定調度
在前面講過,MyISAM儲存引擎的讀取鎖定和寫入鎖定是互斥的,讀取和寫入操作是串行的。那麼,一個進程請求某個 MyISAM表的讀鎖,同時另一個進程也請求同一表的寫鎖,MySQL該如何處理呢?答案是寫進程先獲得鎖。不僅如此,即使讀取請求先到鎖等待佇列,寫入請求後 到,寫鎖也會插到讀鎖請求之前!這是因為MySQL認為寫入請求一般比讀取請求重要。這也正是MyISAM表不太適合於有大量更新操作和查詢操作應用的原 因,因為,大量的更新操作會造成查詢操作很難獲得讀鎖,從而可能永遠阻塞。這種情況有時可能會變得非常糟糕!幸好我們可以透過一些設定來調節MyISAM 的調度行為。
1、透過指定啟動參數low-priority-updates,使MyISAM引擎預設給予讀取請求以優先的權利。
2、透過執行指令SET LOW_PRIORITY_UPDATES=1,使該連線所發出的更新請求優先權降低。
3、透過指定INSERT、UPDATE、DELETE語句的LOW_PRIORITY屬性,降低該語句的優先權。
雖然上面3種方法都是要更新優先,或是查詢優先的方法,但還是可以用其來解決查詢相對重要的應用程式(如使用者登入系統)中,讀鎖等待嚴重的問題。
另外,MySQL也提供了一種折中的辦法來調節讀寫衝突,即給系統參數max_write_lock_count設定一個合適的值,當一個表的讀鎖達到這個值後,MySQL就暫時將寫請求的優先權降低,給讀進程一定獲得鎖的機會。
上面已經討論了寫優先調度機制所帶來的問題和解決方法。這 裡還要強調一點:一些需要長時間運行的查詢操作,也會讓寫入進程「餓死」!因此,應用程式應盡量避免長時間運行的查詢操作,不要總是想用一條SELECT語句來解決問題,因為這種看似巧妙的SQL語句,往往比較複雜,執行時間較長,在可能的情況下可以透過使用中間表等措施對SQL語句做一定的“分解”,使每一步查詢都能在較短時間完成,從而減少鎖定衝突。如果複雜查詢不可避免,應盡量安排在資料庫空閒時段執行,例如一些定期統計可以安排在夜間執行。
後續會為大家講解InnoDB鎖定。
相了解更多相關問題請造訪PHP中文網:Mysql影片教學
#以上是關於mysql鎖機制原理的詳細講解(一)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

了解MySQL和PostgreSQL的並發控制和鎖定機制引言:在資料庫管理系統(DBMS)中,資料庫並發控制和鎖定機制是至關重要的概念。它們用於管理多個使用者並發存取資料庫時的資料一致性和隔離性。本文將探討MySQL和PostgreSQL兩個常見的關係型資料庫管理系統在並發控制和鎖定機制方面的實作機制,並提供對應的程式碼範例。一、MySQL的同時控制與鎖機制MySQL

Golang中鎖機制的效能最佳化技巧,需要具體程式碼範例摘要:Golang是一種高效率的程式語言,廣泛應用於並發程式設計。在多執行緒或分散式環境中,鎖定機制是必不可少的組成部分,但是使用不恰當的鎖定機制可能導致效能下降。本文將介紹幾種Golang中鎖機制的效能最佳化技巧,並提供程式碼範例。關鍵字:Golang、鎖、效能最佳化、程式碼範例介紹鎖定機制是多執行緒或分散式環境中確保資料一

如何使用Java中的鎖機制實現執行緒同步?在多執行緒程式設計中,執行緒同步是一個非常重要的概念。當多個執行緒同時存取和修改共享資源時,可能會導致資料不一致或競態條件的問題。 Java提供了鎖定機制來解決這些問題,並確保執行緒安全的存取共享資源。 Java中的鎖定機制由synchronized關鍵字和Lock介面提供。接下來,我們將學習如何使用這兩種機制來實現執行緒同步。使用sync

隨著互聯網的不斷發展,分散式系統已經成為了應用領域中的熱門話題之一。在分散式系統中,鎖定機制是一個重要的問題,特別是在涉及並發的應用場景中,鎖定機制的效率和正確性越來越受到人們的重視。在這篇文章中,我們將介紹Go語言中的分散式系統和鎖定機制。分散式系統Go語言是一種開源的、現代的程式語言,具有高效、簡潔、易於學習和使用等特點,在工程師團隊中已經得到了廣泛的應用和

如何使用MySQL的鎖定機制處理並發存取衝突在多用戶同時存取資料庫的情況下,可能會出現並發存取衝突的問題。 MySQL提供了鎖定機制用於處理並發存取衝突,本文將介紹如何使用MySQL的鎖定機制來解決這個問題。 MySQL提供了兩種類型的鎖:共用鎖定(SharedLock)和獨佔鎖(ExclusiveLock)。共享鎖可以多個事務同時持有,用於讀取操作;獨佔鎖只能由一

Java作為一種高階程式語言,在並發程式設計上有著廣泛的應用。在多執行緒環境下,為了確保資料的正確性和一致性,Java採用了鎖定機制。本文將從鎖的概念、類型、實作方式和使用場景等面向對Java中的鎖機制進行探討。一、鎖的概念鎖是一種同步機制,用來控制多個執行緒之間對共享資源的存取。在多執行緒環境下,執行緒的執行是並發的,多個執行緒可能會同時修改相同數據,這會導致數

隨著電腦技術的不斷發展和資料規模的不斷增長,資料庫成為了一項至關重要的技術。然而,在Linux系統中使用資料庫還會遇到一些常見的問題,本文將介紹一些常見的Linux系統中的資料庫問題以及它們的解決方法。資料庫連線問題在使用資料庫時,有時會出現連線失敗或連線逾時等問題,造成這些問題的原因可能是資料庫設定錯誤或存取權限不足。解決方法:檢查資料庫的設定文件,確

探索Java多執行緒原理:鎖機制與執行緒安全性導言:在軟體開發領域,多執行緒程式設計是一項非常重要的技能。透過使用多線程,我們可以同時執行多個任務,提高程式的效能和響應度。然而,多執行緒程式設計也帶來了一系列的挑戰,其中最重要的就是執行緒安全性。本文將探討Java多執行緒原理,重點在於鎖機制及其在執行緒安全性中的作用。一、什麼是線程安全性?在多執行緒環境下,如果一個操作不會導致任
