白話數據庫隔離級別

此文會以比較通俗的語言來介紹一個數據庫的隔離級別分別是什么意思,每種隔離級別是如何實現的,又會帶來什么樣的問題。

大部分的程序猿應該都知道,數據庫中有四種隔離級別,分別是讀未提交(Read Uncommited),讀已提交(Read Committed), 可重復讀(Repeatable Read)和串行化(SERIALIZABLE)。除了最后一個以性能為代價換取讀寫安全一致的串行化外,其他三種類型都會有各自在并發讀寫場景下的一些問題。

Read Uncommitted
先從這個最不安全的說起,Read Uncommitted顧名思義就是允許讀取其他事務還未提交的更新操作。這個隔離級別會帶來臟讀,不可重復讀,幻讀一系列的問題。說到這里有必要先解釋下什么是臟讀,不可重復讀和幻讀。

  1. 臟讀
    想一下這樣的一個例子,你在淘寶上拍了一件100元的商品,正準備去付款。這個時候賣家本想對這件商品做一個減價50元的操作,可是由于誤操作選成了漲價50元,所幸的是還未提交。賣家發現了這個問題準備撤銷,然后在這個時候付款程序卻讀到了這個未提交的漲價50元操作并付了款。當你發現的時候去再一次查看商品價格的時候發現還是100元,因為賣家撤銷了剛才的操作。
  2. 不可重復讀
    依然是淘寶買東西的例子,你拍下了一件100元的商品還沒付款,這個時候賣家卻自說自話的去改了價格變成了150元。然后當你付款的時候你會驚訝的發現這件商品莫名其妙的漲價了50元。
  3. 幻讀
    想象一下你是一個淘寶賣家,然后你想對店鋪里的所有商品做一個降價50的操作。你全選了所有商品,選擇了降價按鈕,輸入了50元。然后在你提交之前,有一個客服往店鋪里面添加了一個新的商品。當你提交之后你會發現剛才的降價操作竟然沒有對所有的商品生效(就是指那個新添加的商品),好像之前的全選漏掉了一個商品似的。

說到這里,大家應該可以明白為什么Read Uncommitted會發生所有上述這三種問題了吧。它都能讀取別人還沒有保存的東西了,這能不出問題嗎。。

Read Committed
讀已提交解決了臟讀的問題,以上面臟讀中的場景為例,當你設置了讀已提交級別之后,數據庫會保證你只能讀到那些已經提交的值。如果有一個事務正在修改某一條記錄,數據庫會給這條記錄加上一個排他鎖,意思是只有當前事務可以訪問這條記錄,其他要訪問的人都先等著,等我改完了你再去弄你的事。
但是這個級別依然無法解決不可重復讀和幻讀的問題,拿不可重復讀來說,我有一個事務A先讀取了一條包含金額為100的記錄,想對它做一個降價50元的操作。同時有一個事務B對這條記錄做了一個漲價50的操作并且提交。這個時候事務A如果在去讀一次數據庫就會發現金額變成了150,和之前不一樣了。

Repeatable Read
可重復讀級別解決了不可重復讀的問題,數據庫會在程序讀數據的時候加上一個共享鎖(讀的程序可以共享某條記錄,但是寫就不行),在程序寫數據的時候加上一個排他鎖(一加上排他鎖,其他程序讀或者寫都不行了)。這樣一來,大家想像是不是就能解決可重復讀的問題了?以上面的場景為例,在事務A讀取了金額為100的記錄的時候,數據庫會給這條記錄加上一個共享鎖,也就是說事務B是不可能對這條記錄進行修改的,直到事務A釋放了鎖以后。

Serializable
最后這個也是最嚴苛的事務隔離機制,可以理解為只要有一個程序在操作某條記錄,無論是讀或者寫,其他所有的程序都必須等著直到之前那個程序完成事務。這個事務隔離級別會嚴重影響性能,試想一下雙11的時候成千上萬的用戶在瀏覽淘寶,每個用戶必須先等待之前用戶的讀取(商品數據等)完成之后服務器才能響應是一種什么樣的體驗。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容