資料庫併發事務

2021-08-21 18:10:57 字數 2099 閱讀 3167

比如有乙個方法a,在a的內部有兩次同樣的select查詢,但是在兩次select之間方法b對資料庫進行了修改,那麼查詢到的a兩次查詢到的內容是否一致呢,這其實就是資料庫的 」不可重複讀/幻讀「 問題

這裡用spring+hibernate+mysql實驗,如果方法a不在事務環境下執行,那麼查詢到的兩次結果將會不同

@suppresswarnings("unchecked")

@override

public

list

getall()

可以看到斷點在第66行,這時第66行還未執行,第65行的查詢結果裡有三條記錄,如果這時資料庫被刪除了一條記錄,查詢的結果就會少一條

此時讓**執行一步就可以看見查詢結果只有兩條了

如果在事務環境裡執行,那麼修改資料庫也不會影響查詢結果

@transactional

//注意這裡加了事務的註解

這時刪除資料庫資料,或者修改資料庫資料都不會影響兩次查詢的結果的一致性

那麼這是怎麼實現的呢,mysql預設情況下乙個事務在整個過程中可以多次重複執行某個查詢,並且每次返回的記錄都相同。該級別可以防止髒讀和不可重複讀。

幻讀是如何防止的?mysql的innodb引擎提供的mvcc解決了幻讀問題,mvcc對不同的事務儲存了不同的資料版本

比如說有乙個**審批表,乙個欄位是**,乙個欄位是審批是否同意,員工只能修改**,領導只能對**做出審批,那就要防止領導與員工同時操作這條記錄,不然會出現領導批准了300元的**,但同時員工卻將**修改為了200元。

一共有兩種解決方案

也就是有個人訪問這一行,別人訪問就會阻塞,具體可以由lockmode這個類實現

@transactional

public void update(long id, price newprice)

大家同時可以訪問,最後只有乙個人會成功,其他人可以通過反覆重試事務來完成,這種一般是在表裡加個字段version來實現

@version

private

int version;

這裡只列出一種併發情形,領導的審批事務先執行完畢,其它與這個處理方式類似

員工事務

領導事務

開始事務

開始事務

從資料庫獲取**資訊(price:2,status:未審批,version:1)

從資料庫獲取**資訊(price:2,status:未審批,version:1)

設定審批狀態(price:2,status:已審批,version:1)

設定**(price:3,status:未審批,version:1)

開始提交事務,此時資料庫裡version為1

提交成功

(price:2,status:已審批,version:2)

開始提交事務,此時資料庫裡version為2,與自身version不同

提交失敗

提示使用者重新整理頁面

其實通過hibernate的查詢語句就能看出來原理,在update 的時候where條件後除了id外還新增了乙個version欄位,如果資料庫裡的version和和自身的不一樣,那查詢出來的結果肯定為空,這時hibernate肯定會丟擲異常,可以捕獲這個異常進行後續處理,比如提示使用者當前的資料已經不是最新的資料。

id=? and

version=?

資料庫事務與併發

資料庫事務必須具備acid特徵 1 原子性 指整個資料事務是不可分割的工作單元。只有事務中所有操作執行成功,才算整個事務成功 事務中任何乙個sql語句執行失敗,那麼已經執行成功的sql語句也必須撤銷,資料庫狀態應該退回到執行事務前的狀態。2 一致性 指資料庫事務不能破壞關係資料的完整性以及業務邏輯上...

資料庫事務併發問題

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

oracle資料庫事務併發操作

1 丟失資料修改 當兩個或多個事務選擇同一行,然後基於最初選定的值更新該行時,會發生丟失更新問題。每個事務都不知道其它事務的存在。最後的更新將重寫由其它事務所做的更新,這將導致資料丟失。2 讀 髒 資料 髒讀 讀 髒 資料是指事務t1修改某一資料,並將其寫回磁碟,事務t2讀取同一資料後,t1由於某種...