在多使用者環境中,在同一時間可能會有多個使用者更新相同的記錄,這會產生衝突。這就是著名的併發性問題。
典型的衝突有:
丟失更新:乙個事務的更新覆蓋了其它事務的更新結果,就是所謂的更新丟失。例如:使用者a把值從6改為2,使用者b把值從2改為6,則使用者a丟失了他的更新。
髒讀:當乙個事務讀取其它完成一半事務的記錄時,就會發生髒讀取。例如:使用者a,b看到的值都是6,使用者b把值改為2,使用者a讀到的值仍為6。
不可重複讀:事務 a 讀取了事務 b 已提交的更改資料
幻讀:事務 a 讀取了事務 b 已提交的新增資料。
為了解決這些併發帶來的問題。 我們需要引入併發控制機制。
悲觀鎖(pessimistic lock), 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。
悲觀鎖實現方式:
運用資料庫裡面的鎖機制:
詳解參考:
共享鎖(shared lock)
更新鎖(update lock)------------------》為了解決死鎖
排他鎖(獨佔鎖 exclusive locks)---》即其它事務既不能讀,又不能改排他鎖鎖定的資源。
意向鎖(intent locks)--------》意向鎖就是說乙個表門口設定乙個標識
計畫鎖(schema locks)-------》鎖不允許任何其它session連線該錶。連都連不了這個表了,當然更不用說想對該錶執行什麼sql語句了。
樂觀鎖(optimistic lock), 顧名思義,就是很樂觀,每次去拿資料的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個資料,可以使用版本號等機制。樂觀鎖適用於多讀的應用型別,這樣可以提高吞吐量,像資料庫如果提供類似於write_condition機制的其實都是提供的樂觀鎖。(樂觀鎖不能解決髒讀的問題。)
樂觀鎖實現方式:
1.使用資料版本(version)記錄機制實現,這是樂觀鎖最常用的一種實現方式。何謂資料版本?即為資料增加乙個版本標識,一般是通過為資料庫表增加乙個數字型別的 「version」 欄位來實現。當讀取資料時,將version欄位的值一同讀出,資料每更新一次,對此version值加一。當我們提交更新的時候,判斷資料庫表對應記錄的當前版本資訊與第一次取出來的version值進行比對,如果資料庫表當前版本號與第一次取出來的version值相等,則予以更新,否則認為是過期資料。
2.樂觀鎖定的第二種實現方式和第一種差不多,同樣是在需要樂觀鎖控制的table中增加乙個字段,名稱無所謂,字段型別使用時間戳(timestamp), 和上面的version類似,也是在更新提交的時候檢查當前資料庫中資料的時間戳和自己更新前取到的時間戳進行對比,如果一致則ok,否則就是版本衝突。
如何提高併發效率
悲觀鎖:利用資料庫本身的鎖機制實現。通過上面對資料庫鎖的了解,可以根據具體業務情況綜合使用事務隔離級別與合理的手工指定鎖的方式比如降低鎖的粒度(鎖的粒度就是指鎖的生效範圍,就是說是行鎖,還是頁鎖,還是整表鎖)等減少併發等待。
樂觀鎖:利用程式處理併發。原理都比較好理解,基本一看即懂。方式大概有以下3種
對記錄加版本號.
對記錄加時間戳.
對將要更新的資料進行提前讀取、事後對比。
不論是資料庫系統本身的鎖機制,還是樂觀鎖這種業務資料級別上的鎖機制,本質上都是對狀態位的讀、寫、判斷。
兩種鎖各有優缺點,不可認為一種好於另一種,像樂觀鎖適用於寫比較少的情況下,即衝突真的很少發生的時候,這樣可以省去了鎖的開銷,加大了系統的整個吞吐量。但如果經常產生衝突,上層應用會不斷的進行retry,這樣反倒是降低了效能,所以這種情況下用悲觀鎖就比較合適。悲觀鎖用於經常修改的情況。
樂觀鎖和悲觀鎖的區別
悲觀鎖 pessimistic lock 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。樂觀鎖 optim...
樂觀鎖和悲觀鎖的區別
來自 悲觀鎖 pessimistic lock 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。樂觀鎖 op...
樂觀鎖和悲觀鎖的區別
悲觀鎖 pessimistic lock 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。樂觀鎖 optim...