1. 程式人生 > >事務的介紹以及事務隔離級別

事務的介紹以及事務隔離級別

什麼是事務

在資料庫操作中,一項事務(Transaction) 是由一條或多條操作資料庫的SQL語句組成的一個不可分割的工作單元。當事務中的所有操作都正常完成時,整個事務才能被提交到資料庫中,如果有一項操作沒有完成,則整個事務會被回滾。

其實事務總結起來理解為:邏輯上的一組操作,組成這組操作的各個單元,要麼一起成功,要麼一起失敗。

事務(Transaction)的四個特性及其ACID屬性

事務有很嚴格的定義,需要同時滿足四個特性,即原子性、一致性、隔離性、永續性。這四個特性通常稱之為ACID特性,具體如下:

  • 原子性(Automicity):事務是一個原子操作單元,其對資料的修改,要麼全都執行,要麼全都不執行。
  • 一致性(Consistent):在事務開始和完成時,資料都必須保持一致狀態。這意味著所有相關的資料規則都必須應用於事務的修改,以保持資料的完整性;事務結束時,所有的內部資料結構(如B樹索引或雙向連結串列)也都必須是正確的。
  • 隔離性(Isolation):資料庫系統提供一定的隔離機制,保證事務在不受外部併發操作影響“獨立”環境執行。這意味著事務處理過程中的中間狀態對外部是不可見的,反之亦然。
  • 永續性(Durability):永續性也稱永久性(permanence),指一個事務一旦提交,它對資料庫中資料的改變就應該是永久性的。系統故障不會對其有任何影響。

併發事務處理帶來的問題

相對於序列處理來說,併發處理能力大大增加資料庫資源的利用率,提高資料庫系統的事務吞吐量,從而可以支援更多的使用者。但併發事務處理也會帶來一些問題,主要包括以下幾種情況。

  • 更新丟失(Lost Update):當兩個或多個事務選擇同一行,然後基於最初選定的值更新該行時,由於每個事務都不知道其他事務的存在,就會發生丟失更新問題—–最後的更新覆蓋了由其他事務所做的更新。例如,兩個編輯人員製作了同一文件的電子副本。每個編輯人員獨立地更改其副本,然後儲存更改後的副本,這樣就覆蓋了原始文件。最後儲存其更改副本的編輯人員覆蓋另外一個編輯人員所做的更改。如果在一個編輯人員完成並提交事務之前,另一個編輯人員不能訪問同一檔案,則可避免此問題。
  • 髒讀(Dirty Reads):一個事務正在對一條記錄做修改,在這個事務完成並提交前,這條記錄的資料就處於不一致狀態;這時,另一個事務也來讀取同一條記錄,如果不加控制,第二個事務讀取了這些“髒”資料,並據此做進一步的處理,就會產生未提交的資料依賴關係。這種現象被形象的叫做“髒讀”。
  • 不可重複讀(Non-Repeatable Reads):一個事務在讀取某些資料後的某個時間,再次讀取以前讀過的資料,卻發現其讀出的資料已經發生了改變或某些記錄已經被刪除了!這種現象叫做“不可重複讀”。
  • 幻讀(Phantom Reads):一個事務按相同的查詢條件重新獲取以前檢索過的資料,卻發現其他事務插入了滿足其查詢條件的新資料,這種現象就稱為“幻讀”。

事務的隔離級別

在上面講到的併發事務處理帶來的問題中,“更新丟失”通常是應該·完全避免的。但防止更新丟失,並不能單靠資料庫事務控制器來解決,需要應用程式對要更新的資料加必要的鎖來解決,因此,防止更新丟失應該是應用的責任。

這裡寫圖片描述

為了避免事務併發問題的發生,在標準SQL規範中,定義了4個事務隔離級別,不同的隔離級別對事務的處理不同。

這裡寫圖片描述

隔離級別——————–含義

READ_UNCOMMITTED——————–允許你讀取還未提交的改變了的資料。可能導致髒、幻、不可重複讀

READ_COMMITTED——————–允許在併發事務已經提交後讀取。可防止髒讀,但幻讀和不可重複讀仍可發生

REPEATABLE_READ——————–對相同欄位的多次讀取是一致的,除非資料被事務本身改變。可防止髒、不可重複讀,但幻讀仍可能發生

SERIALIZABLE——————–完全服從ACID的隔離級別,確保不發生髒、幻、不可重複讀。這在所有的隔離級別中是最慢的,它是典型的通過完全鎖定在事務中涉及的資料表來完成的。

事務的隔離級別,是由資料庫提供的,並不是所有資料庫都支援四種隔離級別

MySQLREAD_UNCOMMITTEDREAD_COMMITTEDREPEATABLE_READSERIALIZABLE,(預設為REPEATABLE_READOracle:READ_UNCOMMITTEDREAD_COMMITEEDSERIALIZABLE,(預設為READ_COMMITEED

在使用資料庫時候,隔離級別越高,安全性越高,效能越低。

實際開發中,不會選擇最高或者最低隔離級別,選擇READ_COMMITTED(Oracle預設)REPEATABLE_READ(MySQL預設)

參考書籍:

《深入淺出MySQL》