悲觀鎖(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中已經提交的操作
髒讀:事務中的修改,即使沒有提交,對其他事務也都是可見的。事務可以讀取未提交的資料,這也稱為髒讀。
幻讀:指的是當某個事務在讀取某個範圍內的記錄時,另外乙個事務又在該範圍內插入了新記錄,當之前的事務再次讀取該範圍內的記錄時,會產生幻行。innodb和xtradb儲存引擎通過多版本併發控制(mvvc)解決了幻讀的問題。
事務隔離級別為可重複讀的情況下:
序列化和可重複讀的實驗測試結果:基於mysql版本5.7.22
可重複讀
事務一事務二
事務一結果
事務二結果
步驟一begin
begin
步驟二select
select
結果(1)
結果(2)
步驟三update id=9
步驟四select
select
出現update的結果(3)
與(2)一致(4)
步驟五update id=9
此時阻塞狀態(可能超時)
步驟六select
select
與(3)結果一致(5)
與(2)結果一致(6)
步驟七commit
步驟八select
select
與(3)一致(7)
與(6)一致(8)----------此時體現了可重複讀的特點,無論事務一如何修改,是否提交,事務二查詢的結果是一致的。
步驟九update id=9
這裡有人說mysql沒有徹底解決幻行的問題,我認為那是概念的混淆,序列化是可以避免這個問題的。
事務一提交後執行成功,此時結果按照事務二的結果為準,更新時所以用id為更新條件,否則可能更新失敗,應為這個條資料的內容已經被事務一更改
步驟十select
select
與(3)一致(9)
出現事務二update的結果(10)
步驟十一
commit
步驟十二
select
select
與(12)一致(11)
與(10)一致(12)
可重複讀
事務一事務二
事務一結果
事務二結果
步驟一begin
begin
步驟二select
select
結果(1)
結果(2)
步驟三insert
步驟四select
select
出現i事務一nsert的結果(3)
與(2)一致(4)
步驟五insert
步驟六select
select
與(3)結果一致(5)
出現事務二insert的結果(6)但是如果id是自增的情況,id會在事務一之後,因為事務先執行的操作,即使沒有提交。
步驟七commit
步驟八select
select
與(3)一致(7)
與(6)一致(8)----------按照幻讀的概念此時應該出現幻行,但是沒有出現事務一增加的資料,應為mysql已經解決的幻行的問題。
步驟九update /delete id=事務一新增的id
雖然看不見資料,但是可以對資料進行更新和刪除修改的操作,因為資料已經實際存在了,查詢的時候是從檢視中得到的資料。而更新不是,並且更新完就可以看見這條資料
步驟十select
select
與(3)一致(9)
出現事務二update/delete的結果(10)
步驟十一
commit
步驟十二
select
select
與(12)一致(11)
與(10)一致(12)
共享鎖和排他鎖:也叫讀鎖和寫鎖。
讀鎖是共享的,或者說是相互不阻塞的。即多個客戶在同一時刻可以同時讀取同乙個資源,互不干擾。
寫鎖是排他的,也就是說乙個寫鎖會阻塞其他的寫鎖和讀鎖。只有這樣,才能確保在給定的時間裡,只有乙個使用者能執行寫入,並防止其他使用者讀取正在寫入的同一資源。
我的實驗結果總結:
可重複讀:update、insert加的是讀鎖,因為其他的事務裡面是可以讀取資料的,但是不能做修改的操作。
序列化:select 是讀鎖,因為在select的時候,其他事務是只能select。
update、insert加的是排他鎖,因為在update、insert的時候,其他事務是不能select、insert、delete.
簡單來說,serializable會在讀取的每一行資料上都加鎖。
手動實現加鎖
共享鎖: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;
mysql事務隔離級別詳解 事務的隔離級別詳解
事務的隔離級別 在資料庫操作中,為了有效保證併發讀取資料的正確性,提出的事務隔離級別。問題的提出 資料庫是要被廣大客戶所共享訪問的,那麼在資料庫操作過程中很可能出現以下幾種不確定情況。更新丟失 兩個事務都同時更新一行資料,乙個事務對資料的更新把另乙個事務對資料的更新覆蓋了。這是因為系統沒有執行任何的...
Mysql的事務隔離級別詳解
mysql的事務隔離級別詳解 什麼是事務 事務是應用程式中一系列嚴密的操作,所有操作必須成功完成,否則在每個操作中所作的所有更改都會被撤消。也就是事務具有原子性,乙個事務中的一系列的操作要麼全部成功,要麼乙個都不做。事務的結束有兩種,當事務中的所有步驟全部成功執行時,事務提交。如果其中乙個步驟失敗,...
MySQL事務,事務隔離級別詳解
1 什麼是事務指作為單個邏輯工作單元執行的一系列操作,要麼完全地執行,要麼完全地不執行。2 事務的4個特性原子性 atomicity 一致性 consistency 隔離性 isolation 永續性 durability 3 每個特性的意思 原子性原子性是指事務是乙個不可再分割的工作單位,事務中的...