1. 程式人生 > >資料庫併發可能存在的問題和資料庫隔離級別

資料庫併發可能存在的問題和資料庫隔離級別

資料庫併發操作存在的異常情況:
1.更新丟失(LostUpdate):
A和B事務併發執行,A事務執行更新後,提交;B事務在A事務更新後,B事務結束前也做了對該行資料的更新操作,然後回滾,則兩次更新操作都丟失了。

第一類丟失更新(回滾丟失,Lost update)。
在事務A期間,事務B對資料進行了更新;在事務A撤銷之後,覆蓋了事務B已經提交的資料。
SQL92沒有定義這種現象,標準定義的所有隔離界別都不允許第一類丟失更新發生。

第二類丟失更新(覆蓋丟失/兩次更新問題,Second lost update)。
在事務A期間,事務B對資料進行了更新;在事務A提交之後,覆蓋了事務B已經提交的資料。
第二類丟失更新,實際上和不可重複讀是同一種問題。

2.髒讀取(DirtyReads):
A和B事務併發執行,B事務執行更新後,A事務查詢B事務沒有提交的資料,B事務回滾,則A事務得到的資料不是資料庫中的真實資料。也就是髒資料,即和資料庫中不一致的資料。

3.不可重複讀取(Non-repeatableReads):
 A和B事務併發執行,A事務查詢資料,然後B事務更新該資料並提交,A再次查詢該資料時,發現該資料變化了。

4.幻讀(PhantomReads):也稱為幻像(幻影)。
A和B事務併發執行,A事務查詢資料,B事務插入或者刪除資料並提交,A事務再次查詢發現,結果集中,有以前沒有的資料或者以前有的資料消失了。

為了避免上面出現幾種情況在標準SQL規範中定義了4個事務隔離級別,不同隔離級別對事務處理不同。
1. READ-UNCOMMITTED未授權讀取/未提交讀
允許髒讀取但不允許更新丟失。
如果一個事務已經開始寫資料,則另外一個事務不允許同時進行寫操作,但允許其他事務讀此行資料。通過“排他寫鎖”實現。

2. READ-COMMITTED授權讀取/提交讀
允許不可重複讀取但不允許髒讀取。
更新語句提交以後別的事務才能讀到這個改變。讀取資料的事務允許其他事務繼續訪問該行資料,但是未提交的寫事務將會禁止其他事務訪問該行。通過“瞬間共享讀鎖”和“排他寫鎖”實現,
在此隔離級下,SELECT命令不會返回尚未提交(Committed)的資料,也不能返回髒資料。

3. REPEATABLE-READ可重複讀取
禁止不可重複讀取和髒讀取。但是有時可能出現幻影資料
在同一個事務裡面先後執行同一個查詢語句的時候,確保得到的結果是一樣的。讀取資料的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。通過“共享讀鎖”和“排他寫鎖”實現,
在此隔離級下,用SELECT命令讀取的資料在整個命令執行過程中不會被更改。此選項會影響系統的效能,非必要情況最好不用此隔離級。

4. SERIALIZABLE序列/可序列讀。
事務只能一個接著一個地執行,但不能併發執行。如果僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的資料不會被剛執行查詢操作事務訪問到。