分布式鎖
疑問??什麼是共享鎖??
共享鎖=共享讀鎖,排他鎖=獨佔寫鎖
鎖機制與innodb鎖演算法
在關係型資料庫中,可以按照鎖的粒度把資料庫鎖分為行級鎖(innodb引擎)、表級鎖(myisam引擎)和頁級鎖(bdb引擎 )。
myisam採用表級鎖(table-level locking)。innodb支援行級鎖(row-level locking)和表級鎖,預設為行級鎖。
innodb實現了行級鎖,頁級鎖,表級鎖。
行級鎖,表級鎖和頁級鎖對比
行鎖如何實現?
innodb是基於索引來完成行鎖
select * from tab_with_index where id = 1 for update;
-- for update 可以根據條件來完成行鎖鎖定,並且 id 是有索引鍵的列,如果 id不是索引鍵那麼innodb將完成表鎖,併發將無從談起
鎖演算法:3種
record lock:單個行記錄上的鎖
gap lock:間隙鎖,鎖定乙個範圍,不包括記錄本身
為了阻止多個事務將記錄插入到同一範圍內,這會導致幻讀問題。
next-key lock:record+gap 鎖定乙個範圍,包含記錄本身
innodb對於行查詢採用此
何為死鎖?
兩個或多個事務在同一資源上相互占用,並請求鎖定對方的資源,從而導致惡性迴圈的現象。
常見的解決死鎖的方法
1、如果不同程式會併發訪問多個表,盡量約定以相同的順序訪問表,可以大大降低死鎖機會。如果業務處理不好可以用分布式事務鎖或者使用樂觀鎖2、在同乙個事務中,盡可能做到一次鎖定所需要的所有資源,減少死鎖產生概率;
3、對於非常容易產生死鎖的業務部分,可以嘗試使用公升級鎖定顆粒度,通過表級鎖定來減少死鎖產生的概率;
先來看看功能:
分布式鎖使用者位於不同的機器中,所獲取成功後,才可以對共享資源進行操作
鎖具有重入的功能:即乙個使用者可以多次獲取某個鎖
獲取鎖有超時的功能:超過指定的時間,還未獲取成功,則返回獲取失敗
自動容錯功能:a機器獲取鎖lock1之後,在釋放lock1之前,機器a掛掉了,導致鎖lock1還未釋放。結果就是lock1一直被機器a占有。分布式鎖能自動解決:持有鎖規定持有超時時間,超時還未釋放時,其餘機器將爭奪該鎖。
假設不會發生併發衝突,只在提交操作時檢查是否違反資料完整性。在修改資料的時候把事務鎖起來,通過version的方式來進行鎖定。
實現方式:一般會使用版本號機制或cas演算法實現。
在修改表中資料記錄過程如下:
select獲取記錄r1
對r1進行編輯
update更新r1
存在什麼問題呢?
當a、b兩個執行緒同時執行到步驟1,這倆獲取的r1資料是一致的,然後同時執行步驟2,最後執行步驟3,最終2個執行緒都會更新成功。如何解決呢?但是後乙個執行的執行緒會把前乙個執行緒更新update的結果給覆蓋掉,這就是併發修改資料的問題
在表中新增乙個版本號,每次更新資料時將版本號作為條件,執行一次更新就版本號+1,過程優化一下,如下:
開啟事務start transaction
select獲取記錄r1,宣告變數v=r1.version
對r1進行編輯
執行更新update
update r1 set version=version+1 where user_id=#user_id# and version=#v#;
步驟4中更新update返回影響的行數,將其記錄在count中,然後根據count來判斷提交事務?回滾事務?
if
(count==1)
else
步驟4中,當多個執行緒同時執行到步驟2時,獲取到的記錄r1是一樣的,但當執行到步驟4時,資料庫對update的這行資料加鎖,確保併發情況下排隊執行
故只有第一次執行update更新操作會返回1,其餘執行緒的更新update操作回返回0,根據count值確定事務提交 / 回滾
所有執行緒執行select查詢時,執行緒的資料v都是r1記錄的版本:上面這種利用版本號的方式就是樂觀鎖,確保了資料併發修改過程中正確性v=r1.version
但經過一次更新update後,r1記錄+1,但其餘執行緒的資料v還是原始的version資料,故不可能執行。
update r1 set version=version+1 where user_id=#user_id# and version=#v#;
考慮⼀個問題:⽐如a機會獲取了key1的鎖,並設定持有鎖的超時時間為10秒,但是獲取鎖之後,執⾏了⼀段業務操作,業務操作耗時超
過10秒了,此時機器b去獲取鎖時可以獲取成功的,此時會導致a、b兩個機器都獲取鎖成功了,都在執⾏業務操作,這種情況應該怎麼處
理?假定會發生併發衝突,遮蔽一切可能違反資料完整性的操作。在查詢完資料的時候就把事務鎖起來,直到提交事務。
實現方式:使用資料庫中的鎖機制
應用場景:
樂觀鎖多讀,悲觀鎖多寫
Mysql系列之鎖機制
一般乙個程式滿,從消耗的角度,乙個是cpu,乙個是io,但有的時候mysql慢,是因為某條sql不小心把整個表給鎖了。鎖是計算機協調多個程序或執行緒併發訪問某一資源的機制。在資料庫中,除了傳統的計算機資源 如cpu,ram,i o 的爭用外,資料也是供很多使用者共享的資源。如何保證資料併發訪問的一致...
MySQL鎖系列(四)之 undo log
1 redo 記錄的是對頁的重做日誌,undo 記錄的是對事務的逆向操作 2 undo 會產生redo,undo的產生也會伴隨這redo的產生,因為重啟恢復的時候,可以通過redo還原這些undo的操作,以達到回滾的目的1 用於對事務的回滾 2 用於mvcc 在mysql5.1的年代,乙個mysql...
MYSQL系列之 鎖與死鎖
mysql 裡面的鎖大致可以分成全域性鎖 表級鎖和行鎖三類 全域性鎖mysql 提供了乙個加全域性讀鎖的方法,命令是 flush tables with read lock ftwrl 當你需要讓整個庫處於唯讀狀態的時候,可以使用這個命令,之後其他執行緒的以下語句會被阻塞 資料更新語句 資料的增刪改...