一、樂觀鎖與悲觀鎖
1.1 樂觀鎖與使用版本號實現樂觀鎖
樂觀鎖假設認為資料一般情況下不會造成衝突,所以在資料進行提交更新的時候,才會正式對資料的衝突與否進行檢測,如果發現衝突了,則對使用者返回錯誤資訊,讓使用者決定如何去處理。 實現方式為版本號和時間戳。
使用版本號時,可以在資料初始化時指定乙個版本號,每次對資料的更新操作都對版本號執行+1操作。並判斷當前版本號是不是該資料的最新的版本號。// 1.查詢出商品資訊
select status, version from t_goods where id=#;
// 2.根據商品資訊生成訂單
// 3.修改商品status為2
update t_goods set status=2,version=version+1 where id=# and version=#;
可以看出第三條sql語句的where條件是version=#,也就是version欄位沒有發生變化的時候才執行更新操作,version欄位沒有變化就意味著在讀取version與修改version期間沒有事務修改資料,那麼version也就不會發生變化,也就可以執行更新操作。
1.2 悲觀鎖
悲觀鎖指的是外界對資料修改持保守態度(悲觀),因此,在整個資料處理過程中,將資料處於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制。具體包括行鎖、表鎖等。
二、myisam的表級鎖
mysql的myisam儲存引擎只支援表級鎖,有兩種模式:表共享讀鎖(table read lock)和表獨佔寫鎖(table write lock)。鎖模式的相容性如下none讀鎖寫鎖讀鎖相容相容衝突
寫鎖相容衝突衝突
也就是說對於myisam表的讀操作不會因為不同程序訪問資源而發生阻塞,而對於myisam表的寫操作會阻塞其他使用者對同一表的讀和寫操作。
讀鎖和寫鎖的加鎖方式以及解鎖方式分別為:lock table table_name read;
lock table table_name write;
unlock tables;
在讀鎖加鎖期間,不管是當前session還是其他session都是可以讀取資料的,但是加鎖的session不可以更新資料,因為加的是讀鎖,其餘的session的更新操作會被阻塞等待直到讀鎖釋放才會更新成功。
在寫鎖加鎖期間,只有當前session可以執行查詢或更新操作,因為寫鎖與讀鎖以及寫鎖不相容,其餘session的查詢與更新操作會被阻塞等待直到擁有鎖的session釋放鎖為止。
可以通過如下命令獲取myisam表級鎖的爭用情況:show status like 'table%';
該命令顯示的具體引數含義如下:table_locks_immediate:產生表級鎖定的次數;
table_locks_waited:出現的比較鎖定爭用而發生等待的次數;
如果table_locaks_waited的值比較高,那麼說明存在比較嚴重的表級鎖爭用情況。myisam在讀操作佔主導的情況下是高效的,可一旦出現大量讀寫操作併發,與innodb相比,myisam的執行效率就會直線下降。
myisam儲存引擎有個系統變數,concurrent_insert,專門用以控制其併發插入的行為,其值分別是0、1、2。解釋如下:當值為0時,不允許併發插入;
當值為1時,如果表中沒有被刪除的行,myisam允許在乙個程序讀表的同時,另乙個程序從表尾插入記錄;
當值為2時,無論表中有沒有被刪除的行,都允許在表尾併發插入記錄。
三、innodb行級鎖
innodb支援行級鎖,支援事務處理。在處理資料量上innodb支援海量資料,並且在具有良好的索引的基礎上,innodb的查詢速度要比myisam快。
3.1 注意:事務與併發的區別
事務通常包含一系列更新操作,這些更新操作是乙個不可分割的邏輯工作單元。要麼全部成功,要麼全部失敗。乙個session或程序或執行緒的某個操作如果包含一系列不可分割的邏輯單元那麼就是乙個事務,而併發指的是有可能包含事務操作的多程序/執行緒同時對某一資源進行操作,所以,在多程序/執行緒併發中,保持某程序/執行緒事務的完整性是安全且高效併發的基礎。也就是說,在多程序/執行緒併發操作某一資源時,某個程序/執行緒的對資源一系列更新操作的抽象(也就是事務)安全(即事務安全)必須得到保證,不然就會產生資料錯誤。包含以下幾種:丟失更新:乙個事務讀取資料並提交修改,覆蓋了從上次讀取之後其他事務提交的修改(不是基於最新的資料進行修改);
讀髒資料:乙個事務讀到另外乙個事務還沒有提交的資料;
不可重複讀:乙個事務兩次讀取一條記錄之間有其他事務修改了改記錄,導致兩次讀取的結果不一樣;
幻讀:乙個事務兩次讀取多條記錄之間有其他事務進行了新增或刪除的操作,導致兩次讀取記錄的數量不一致。
因此為了避免資料錯誤,必須保證併發事務的安全性。可以通過資料庫隔離級別來實現不同程度上的安全隔離。如下縱向為隔離級別、橫向為讀資料一致性及允許併發的***讀資料一致性髒讀不可重複讀幻讀未提交讀最低級別,只能保證不讀取物理上損壞的資料是是是
已提交讀語句級否是是
可重複讀事務級否否是
可序列化最高端別,事務級否否否
可見,事務的隔離級別越嚴格,併發的***就小,但付出的代價越大。
事務與併發總結:事務安全是在併發**現的,沒有併發就不會產生事務安全。myisam不支援事務即不支援一系列不可分割的更新操作組成的邏輯工作單元,所以就不會產生事務安全問題。但是innodb支援事務操作,那麼就會存在上述事務安全問題。為了解決上述事務安全問題,必須首先關閉mysql自動提交(因為自動提交會使得每一條更新語句被執行從而資料被持久化),然後執行一系列更新語句組成的邏輯工作單元後再顯式提交事務(commit),出問題還可以回滾(rollback)。也可以不關閉自動提交,直接顯式開啟事務(start transaction)即可也是同樣的效果。這是乙個session/程序/執行緒對自己事務的處理方式從而保證自己的一系列操作是完整的,但是高併發環境下,程序/執行緒之間各自事務的安全性保證則要通過事務的隔離級別來實現。同樣的,併發操作必須加鎖。即執行緒/程序的原子事務的子操作必須加鎖保證對某一條記錄的修改是獨佔的,程序/執行緒之間的事務安全通過隔離級別來保證。
3.2 innodb行級鎖模式、事務下共享鎖與排它鎖的使用流程鎖模式共享鎖(s)排它鎖(x)意向共享鎖(is)意向排它鎖(ix)共享鎖(s)相容衝突相容衝突
排它鎖(x)衝突衝突衝突衝突
意向共享鎖(is)相容衝突相容相容
意向排它鎖(ix)衝突衝突相容相容
各個鎖的含義如下:共享鎖(s):允許乙個事務讀一行資料時,阻止其他的事務讀取相同資料的排它鎖;
排它鎖(x):允許獲得排它鎖的事務更新資料,阻止其他事務取得相同資料的共享鎖和排它鎖;
意向共享鎖(is):事務打算給資料行加行共享鎖。事務在給乙個資料行加共享鎖前必須先取得該錶的is鎖;
意向排它鎖(ix):事務打算給資料行加行排它鎖,事務在給乙個資料行加排它鎖前必須先取得該錶的ix鎖。
如果乙個事務請求的鎖模式與當前的鎖模式相容,innodb就將請求的鎖授予該事務,如果兩者不相容,那麼該事務就要等待鎖釋放。
意向鎖是innodb儲存引擎自動加的,對於普通的select語句,innodb不會加任何鎖,對於insert、update、delete語句,innodb會自動給涉及的資料加排它鎖,innodb可以通過如下語句新增共享鎖(s)與排它鎖(x):sql語句 lock in share mode;
sql語句 for update;
使用innodb共享鎖與排它鎖必須滿足以下幾個條件:設定autocommit的值是off或;
表的資料引擎是支援事務的,比如innodb資料引擎;
如果不管autocommit,手段在事務裡執行操作,這個時候要使用begin或者start transaction開啟事務;
不要在鎖定事務規定的時間外使用共享鎖和排它鎖。
之所以有上述四個條件是因為innodb是支援事務的,而innodb又是自動提交的,這和事務一次性提交不符,所以先要關閉事務自動提交,或者直接使用start transaction開啟事務,執行完事務中的sql語句後再提交(commit)。
以上條件也是innodb儲存引擎在支援事務的情況下的獲取共享鎖或排它鎖實現資料操縱的流程。
需要注意的是,innodb行級鎖是通過給索引上的索引項加鎖來實現的,innodb行級鎖只有通過索引條件檢索資料,才使用行級鎖,否則使用表級鎖。
3.3 innodb在不同隔離級別下加鎖的差異
在不同隔離級別下,innodb處理sql語句時所採用的一致性和需要的鎖是不同的。
對於sql語句而言,隔離級別越高,innodb儲存引擎給記錄新增的鎖就越嚴格,產生鎖衝突的可能性就越高(因為高隔離級別是保證了某乙個事務的整體完整性,因此其餘事務就會產生鎖等待),對併發的效能影響就越大。因此,應該盡量使用較低的隔離級別,以降低併發中的鎖爭用的機率。
對於一些需要使用較高隔離級別的情況,可以通過如下操作更換隔離級別:set session transaction isolation level repeatable read;
set session transaction isolation level serializable;
3.4 間隙鎖(net-key鎖)
在更新innodb儲存引擎表中的某個區間資料時,將會鎖定這個區間的所有記錄,即使這個區間中的某條記錄不存在,該條記錄也會被鎖住,這個時候,如果另外乙個session往這個表中新增一條記錄時,此時必須等到上乙個事務釋放鎖資源。
innodb使用間隙鎖的目的,一方面是為了防止幻讀,如果沒有加間隙鎖,如果其他事務新增某個區間的某條記錄,那麼就會發生幻讀;另一方面,是為了滿足其恢復和賦值的需求。
mysql鎖定機制
標籤 空格分隔 mysql 鎖 mysql對於不同儲存引擎支援不同的鎖定機制,myisam和memory儲存引擎採用的是表級鎖 innodb採用行級鎖,也支援表級鎖 bdb儲存引擎採用的是頁級鎖同時也支援表級鎖。行級鎖最大特點是鎖定物件的粒度很小,發生資源競爭的概率就比較小,故而能提高較大的併發處理...
mysql front 鎖定 Mysql鎖機制
鎖是計算機協調多個程序或執行緒併發訪問某一資源的機制。在資料庫中資料其實是一種供大量使用者共享的資源,所以在併發訪問時我們需要保證資料的一致性和有效性,而鎖衝突是影響資料庫併發效能最關鍵的因素之一。所以本篇文章主要討論mysql中鎖機制的特點。mysql的鎖機制包含多種 行鎖,表鎖,讀鎖,寫鎖等,其...
mysql資料庫鎖定機制
為了保證資料的一致完整性,任何乙個資料庫都存在鎖定機制。鎖定機制的優劣直接應想到乙個資料庫系統的併發處理能力和效能,所以鎖定機制的實現也就成為了各種資料庫的核心技術之一。下面將對 mysql 的 innodb 各自的鎖定機制進行較為詳細的分析。總的來說,mysql 各儲存引擎使用了三種型別 級別 的...