資料庫鎖解決併發問題

2021-08-28 19:17:11 字數 1461 閱讀 4494

問題描述:乙個優惠券活動,使用者可以領取優惠券,但是乙個優惠券活動領取數量有限制,所以使用者在領取的時候就需要先統計一下以領用的優惠券數量。 然後在生成這張優惠券領取記錄。那麼此時就會出現併發問題,當多個使用者領取同乙個優惠券活動的時候,他們統計的優惠券已領數量小於限定可領取數量,所以都可以執行生成 優惠券領取記錄的操作,但是剩下的可領取數量可能小於這些使用者數量。

如何來解決這個問題呢,首先我們會想到,在程式中使用synchronized關鍵字來鎖住領取優惠券的方法,那麼就可以實現,當乙個人在領取優惠券的時候其他人等待,但是程式 都是分發到多台伺服器的,在分布式的情況下,這種方法並沒有效果,因為程式中所能做到的只是鎖住單台伺服器上面的操作。

既然程式中無法實現,那麼我們就想到利用資料庫來實現,因為我現在做的這個專案,資料庫是沒用從庫的,只有一台資料庫伺服器,如果資料庫也分布式了,那就要另求它法了。

想到用資料庫解決後,首先想到的是利用事務的原子性來解決,就是統計已領用數量的操作和生成優惠券記錄的操作合成為乙個事務,表面上感覺可以了,但其實這樣做也是錯誤的。 因為多個事務同時處理時,情況也是一樣的,同樣會出現併發問題。

所以單單利用事務還是不行的,還必須使用資料庫的鎖機制。

innodb實現了以下兩種型別的行鎖。

鎖的範圍:行鎖: 對某行記錄加上鎖 ; 表鎖: 對整個表加上鎖

此處我們需要使用的是排它鎖,就是當乙個事物在進行操作的時候,其他事物不能去統計已經領取優惠券的數量,只有領取完成之後才能統計。鎖的範圍是行。

使用排他鎖的方法其實是悲觀鎖機制,我們還有樂觀鎖,接下來就先介紹下二者區別。

悲觀鎖:假定會發生併發衝突,遮蔽一切可能違反資料完整性的操作。

悲觀鎖假定其他使用者企圖訪問或者改變你正在訪問、更改的物件的概率是很高的,因此在悲觀鎖的環境中,在你開始改變此物件之前就將該物件鎖住,並且直到你提交了所作的更改之後才釋放鎖。 悲觀的缺陷是不論是頁鎖還是行鎖,加鎖的時間可能會很長,這樣可能會長時間的限制其他使用者的訪問,也就是說悲觀鎖的併發訪問性不好。

樂觀鎖:假設不會發生併發衝突,只在提交操作時檢查是否違反資料完整性。

樂觀鎖不能解決髒讀的問題。 樂觀鎖則認為其他使用者企圖改變你正在更改的物件的概率是很小的,因此樂觀鎖直到你準備提交所作的更改時才將物件鎖住,當你讀取以及改變該物件時並不加鎖。 可見樂觀鎖加鎖的時間要比悲觀鎖短,樂觀鎖可以用較大的鎖粒度獲得較好的併發訪問效能。但是如果第二個使用者恰好在第乙個使用者提交更改之前讀取了該物件,那麼當他完成了自己的更改進行提交時, 資料庫就會發現該物件已經變化了,這樣,第二個使用者不得不重新讀取該物件並作出更改。這說明在樂觀鎖環境中,會增加併發使用者讀取物件的次數。

如果使用樂觀鎖的方式,我們就需要給資料庫有當前優惠券活動已領取數量的字段,每次我們修改這個欄位的值時對其就行判斷,如果他小於可領取數量,那麼久可以插入 這條優惠券記錄。這樣判斷和更新是在同一條sql中,這樣就利用一條sql的原子性,避免併發衝突

樂觀鎖解決併發問題

為什麼需要鎖 在多使用者環境中,在同一時間可能會有多個使用者更新相同的記錄,這會產生衝突。這就是著名的併發性問題。典型的衝突有 丟失更新 乙個事務的更新覆蓋了其它事務的更新結果,就是所謂的更新丟失。例如 使用者a把值從6改為2,使用者b把值從2改為6,則使用者a丟失了他的更新。髒讀 當乙個事務讀取其...

資料庫事務併發問題

乙個資料庫可能擁有多個訪問客戶端,這些客戶端都可以併發方式訪問資料庫。資料庫中的相同資料可能同時被多個事務訪問,如果沒有採取必要的隔離措施,就會導致各種併發問題,破壞資料的完整性。這些問題可以歸結為 5類,包括 3類資料讀問題 髒讀 幻象讀和不可重複讀 以及 2類資料更新問題 第一類丟失更新和第二類...

資料庫高併發問題

多執行緒多程序 計算密集型任務 使用多程序,因為能python有gil,多程序可以利用上cpu多核優勢 io密集型任務 使用多執行緒,做io切換節省任務執行時間 併發 乙個專案剛開始的時候是為了實現基本功能,隨著版本和功能的迭代,大資料和高併發成了軟體設計必須考慮的問題 本質很簡單,乙個是慢,乙個是...