悲觀鎖和樂觀鎖以及事務的隔離級別
悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。
樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿資料的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個資料,可以使用版本號等機制。樂觀鎖適用於多讀的應用型別,這樣可以提高吞吐量,像資料庫如果提供類似於write_condition機制的其實都是提供的樂觀鎖。
兩種鎖各有優缺點,不可認為一種好於另一種,像樂觀鎖適用於寫比較少的情況下,即衝突真的很少發生的時候,這樣可以省去了鎖的開銷,加大了系統的整個吞吐量。但如果經常產生衝突,上層應用會不斷的進行retry,這樣反倒是降低了效能,所以這種情況下用悲觀鎖就比較合適。
事務隔離級別共有4種:
事務隔離級別 | 髒讀 | 不可重複度 | 幻讀 |
1.未提交讀 | 是 | 是 | 是 |
2.提交讀(不可重複讀) | 否 | 是 | 是 |
3.可重複讀 | 否 | 否 | 是 |
4.序列化 | 否 | 否 | 否 |
mysql的預設事務隔離級別為可重複讀,而Oracle、Sqlserver的預設事務隔離級別都為提交讀(不可重複讀)
1.InnoDB 支援表鎖和行鎖,使用索引作為檢索條件修改資料時採用行鎖,否則採用表鎖。鎖表時在其它的事務中執行會發生等待的現象,時間長的話會有報錯提示。
2 InnoDB 自動給修改操作加鎖,給查詢操作不自動加鎖
3.行鎖相對於表鎖來說,優勢在於高併發場景下表現更突出,畢竟鎖的粒度小。
4. 當表的大部分資料需要被修改,或者是多表複雜關聯查詢時,建議使用表鎖優於行鎖。
5.為了保證資料的一致完整性,任何一個數據庫都存在鎖定機制。鎖定機制的優劣直接影響到一個數據庫的併發處理能力和效能。
舉例說明:不可重複讀
1.事務隔離級別為不可重複讀
2.在兩個事務同時開啟時
3.事務B中,在事務A操作增刪改之前查詢一次資料
4.事務A做了更新或刪除的操作,並提交
5.事務B中,在事務A操作增刪改之後查詢一次資料。兩次查詢結果不一致,可以看見事務A中已經提交的操作
幻讀:在mysql中沒有實現出來,網上有好多的說法。其實過分關注概念也是沒有用的,於是不在研究。
事務隔離級別為可重複讀的情況下:
手動實現加鎖
共享鎖:select * from tableName where ... + lock in share more
排他鎖:select * from tableName where ... + for update
查詢事務的隔離級別:select @@tx_isolation;
設定事務的隔離級別:SET session TRANSACTION ISOLATION LEVEL Serializable;(引數可以為:Read uncommitted,Read committed,repeatable read,Serializable)
開啟事務:start transaction;或者begin;
提交事務:commit;