注意事項
有大量資料的資料庫,要更改定序時,務必下班再做or確認不會卡到別人的事情
隔離級別
參考資料:(https://openhome.cc/Gossip/HibernateGossip/IsolationLevel.html)
參考資料:(https://blog.csdn.net/baidu_37107022/article/details/77481670)
參考資料:(https://read01.com/zh-tw/P2L3na.html#.XM_ICOgzaUk)
隔離性是交易的保證之一,表示交易與交易之間不互相干擾,好像同時間就只有自己的交易存在一樣,隔離性保證的基本方式是在資料庫層面,對資料庫或相關欄位鎖定,在同一時間內只允許一個交易進行更新或讀取。
資料庫有可能發生的問題:
更新遺失(lost update)
二次更新遺失(second lost update)
髒讀(dirty read)
無法重複的讀取(unrepeatable read)
幻讀(phantom read)
隔離級別總共有四種
Read uncommitted
Read committed (SQL Server、Oracle Default)
Repeatable read (MySQL Default)
Serializable
隔離交易的基本方式是鎖定資料庫,但完全的鎖定資料庫實務上並不會這麼作,因為完全的鎖定資料庫將導致嚴重的效能問題,因此實務上會根據資料讀寫更新的頻繁性,設定不同的交易隔離層級(transaction isolation level):
Read uncommitted
當隔離級別設定為 Read uncommitted 時,至少可避免更新遺失的問題。當對同一個欄位資料做更新的時候,第二筆要先等第一筆事務完成。 在 commit 以前的修改 也會被讀取到,這會導致人看到過渡性 or 錯誤的資料。
比如有一項事務,有一筆資料一開始是 A,會先被改成B,最後改成C,接著執行commit。倘若在執行事務時,該筆資料被查詢,有可能就會把B送出去。而這是不應該的,要馬看到 A (原本的),要馬看到C (執行完成的),中間的不穩定、過渡性資料不應該被查詢、造成誤導、錯誤,這就叫做髒讀。
Read committed
當隔離級別設定為 Read committed 時,可以避免髒讀的問題,交易讀取的資料,至少要是已經確認的資料。
基本作法是,讀取的交易不會阻止其他交易,但是一個未確認的更新 會阻止其他所有的交易,但這就會因此影響效能。 有一種作法是 交易正在更新,尚未確定前 都先操作暫存表格。
但還是會有 不可重複讀取 的問題。
不可重複讀取 的概念是:有一項A事務 它先查詢餘額有2000元,確認有足夠的餘額後,先去做其他事情,在最後準備扣除餘額,去做付款的動作。可是在執行完成之前,被另外一項事務B搶先了,直接被超車,把餘額扣掉,這樣A事務執行到最後,就會發生錯誤,提示餘額不足。這就叫做 不可重複讀。
Repeatable read
當隔離級別設定為 Repeatable read 時,可以避免不可重複讀取的問題,他保證 同一交易內兩次讀取的資料必須相同。
基本作法是 讀取交易不會阻止其他的讀取,但是會阻止其他寫入的交易,但這影響效能較大。
但還是會有 幻讀 的問題。
幻讀 的概念是:在同一個事務,有兩個查詢事務,因為兩次查詢之間,被新增、刪除了資料,導致筆數不一致。 就好像產生幻覺。
Serializable
當隔離級別設定為 Serializable 時,可以避免 幻讀 的問題,這是最嚴格的隔離層級,只要有資料不一致的疑慮,交易必須可以循序的一個一個來。(也是因此被叫做 Serializable)
基本作法是 A交易讀取時,B交易若要更新,必須循序。如果A交易需要更新,不論B交易是讀取還是更新,都必須循序。
因為 read uncommited 出錯的機率太大,而 serializable 又嚴重傷害系統效能,所以大部分的應用程式都會選用 read commited 和 repeatable read 這兩個層級。
悲觀鎖和樂觀鎖比較
參考資料:(https://juejin.im/post/6844903742161027079)
悲觀鎖適合寫多讀少的場景。
因為在使用的時候該線程會獨占這個資源,在本文的例子來說就是某個id的文章,如果有大量的評論操作的時候,就適合用悲觀鎖,否則用戶只是瀏覽文章而沒什麼評論的話,用悲觀鎖就會經常加鎖,增加了加鎖解鎖的資源消耗。
樂觀鎖適合寫少讀多的場景。
由於樂觀鎖在發生衝突的時候會回滾或者重試,如果寫的請求量很大的話,就經常發生衝突,經常的回滾和重試,這樣對系統資源消耗也是非常大。
所以悲觀鎖和樂觀鎖沒有絕對的好壞,必須結合具體的業務情況來決定使用哪一種方式。 另外在阿里巴巴開發手冊裡也有提到:
阿里巴巴建議以沖突概率20%這個數值作為分界線來決定使用樂觀鎖和悲觀鎖,雖然說這個數值不是絕對的,但是作為阿里巴巴各個大佬總結出來的也是一個很好的參考。
Last updated