怎麼理解SQL的四個事務隔離級別?

SQL資料庫運維發表於2022-03-24
在關係型資料庫中,事務的隔離性分為四個隔離級別,在解讀這四個級別前先了解一下幾個資料讀取的概念。

高併發情況下 ,事務可能出現的幾種情況: 髒讀、幻讀、不可重複讀

1、髒讀

出現原因:一個事務讀取到了快取中另一個事務未提交的髒資料。

說明:當事務B對data進行了修改但是未提交事務,此時事務A對data進行讀取,並使用事務B修改的資料做業務處理。

2、幻讀( 虛讀

出現原因:一個事務在讀取資料時,另一個事務插入了資料,導致上個事務第二次讀取資料時,資料不一致。

說明:data 表有一條資料,事務A對data進行讀取, 事務B對data進行資料新增 ,此時事務A讀取只有一條資料,而最後實際data是有兩條資料,就好象發生了幻覺一樣情況成為幻讀。

3、不可重複讀

出現原因:讀取資料的同時可以進行修改;

說明:事務A、事務B同時對data進行訪問,事務A對data進行讀取,事務B對data進行修改,當事務A第一次對data進行讀取完後事務B提交,此時當事務A第二次讀取該資料時的資料就與第一次讀取的資料不同,這種情況稱為不可重複讀。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

為了避免上述事務併發問題的出現,在標準的 SQL 規範中定義了四種事務隔離級別,不同的隔離級別對事務的處理有所不同。這四種事務的隔離級別如下。

1)Read Uncommitted(讀未提交)

一個事務在執行過程中,既可以訪問其他事務未提交的新插入的資料,又可以訪問未提交的修改資料。如果一個事務已經開始寫資料,則另外一個事務不允許同時進行寫操作,但允許其他事務讀此行資料。此隔離級別可防止丟失更新。

2)Read Committed(讀已提交)

一個事務在執行過程中,既可以訪問其他事務成功提交的新插入的資料,又可以訪問成功修改的資料。讀取資料的事務允許其他事務繼續訪問該行資料,但是未提交的寫事務將會禁止其他事務訪問該行。 也就是說,在事務處理期間,如果其他事務修改了相應的表,那麼同一事務的多個SELECT語句可能返回不同的結果。 此隔離級別可有效防止髒讀。但會出現不可重複讀。

3)Repeatable Read(可重複讀取)

一個事務在執行過程中,可以訪問其他事務成功提交的新插入的資料,但不可以訪問成功修改的資料。讀取資料的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。也就是說,如果使用者在另外一個事務中執行同條SELECT語句數次,結果總是相同的。(因為正在執行的事務所產生的資料變化不能被外部看到)此隔離級別可有效防止不可重複讀和髒讀。

4)Serializable(可序列化)

提供嚴格的事務隔離。它要求事務序列化執行,事務只能一個接著一個地執行,不能併發執行。此隔離級別可有效防止髒讀、不可重複讀和幻讀。但這個級別可能導致大量的超時現象和鎖競爭,在實際應用中很少使用。

總結:

以上四種隔離級別 最高的是Serializable級別,最低的是Read uncommitted級別 ,當然一般來說,事務的隔離級別越高,越能保證資料庫的完整性和一致性,但相對來說,隔離級別越高,對併發效能的影響也越大。像Serializable這樣的級別,就是以鎖表的方式(類似於Java多執行緒中的鎖)使得其他的執行緒只能在鎖外等待,所以平時選用何種隔離級別應該根據實際情況而定。通常將資料庫的隔離級別設定為 Read Committed,即讀已提交資料, 它能夠避免髒讀取,而且具有較好的併發效能 儘管它會導致 不可重複讀 、幻讀和第二類丟失更新這些併發問題,在可能出現這類問題的個別場合,可以由應用程式採用 悲觀鎖 樂觀鎖 來控制。
在MySQL資料庫中預設的隔離級別為Repeatable read (可重複讀) 。在Oracle資料庫中,只支援Serializeble(序列化)級別和Read committed(讀已提交)這兩種級別, 預設的隔離級別為Read Committed(讀已提交)


想要了解更多資料庫相關知識,歡迎關注個人微信公眾號“SQL資料庫運維”,不定時更新你可能需要的文章!


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70015404/viewspace-2883773/,如需轉載,請註明出處,否則將追究法律責任。

相關文章