MySQL事務(一)認識事務

大雜草發表於2020-12-10

簡單來說,事務就是要保證一組資料庫操作,要麼全部完成,要麼全部失敗。

為什麼要有事務

資料庫中的資料是共享資源,因此資料庫系統通常要支援多個使用者的或不同應用程式的訪問,會出現併發存取資料的現象。

資料庫系統必須對這種併發操作提供一種相應的處理機制來保證,訪問彼此之間不受任何干擾,從而保證資料庫的正確性不受到破壞,這種處理機制稱為“併發控制”。其中事務就是為了保證資料的一致性而產生的一種概念和手段。

事務特性

為了保證資料庫的正確性與一致性,事務要具有4個特性:

  • 原子性(atomicity):一個事務應該是一個不可分割的工作單位,事務中包括的操作要麼都成功,要麼都不成功。
  • 一致性(consistency):事務必須是使資料庫從一個一致性狀態變成另一個一致性狀態。一致性與原子性是密切相關的。
  • 隔離性(isolation):一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的資料在事務未提交前對併發的其他事務是隔離的,併發執行的各個事務之間不能互相影響。
  • 永續性(durability):一個事務一旦成功提交,它對資料庫中資料的改變就應該是永久性的。

併發事務存在的問題

如果不考慮事務的隔離性,會發生以下幾種問題:

髒讀

髒讀是指在一個事務處理過程裡讀取了另一個未提交的事務中的資料。

不可重複讀

不可重複讀是指在對於資料庫中的某條資料,一個事務範圍內多次查詢返回不同的資料值(這裡的不同是指某一條或多條資料的內容前後不一致,但資料條數相同)。

不可重複讀和髒讀的區別是:

  • 髒讀是某一事務讀取了另一個事務未提交的髒資料。
  • 不可重複讀是讀取了其他事務提交的資料。

幻讀

幻讀指的是一個事務在前後兩次查詢同一個範圍的時候,後一次查詢看到了前一次查詢沒有看到的行。

事務隔離級別

  • 讀未提交(read uncommitted):一個事務還沒提交時,它做的變更就能被別的事務看到。
  • 讀提交(read committed):一個事務提交之後,它做的變更才會被其他事務看到。
  • 可重複讀(repeatable read):一個事務執行過程中看到的資料,總是跟這個事務在啟動時看到的資料是一致的。當然在可重複讀隔離級別下,未提交變更對其他事務也是不可見的。
  • 序列化(serializable ):顧名思義是對於同一行記錄,“寫”會加“寫鎖”,“讀”會加“讀鎖”。當出現讀寫鎖衝突的時候,後訪問的事務必須等前一個事務執行完成,才能繼續執行。

下面用一個例子來說明這四種隔離級別:

mysql> create table T(c int) engine=InnoDB;
mysql> insert into T(c) values(1);
MySQL事務(一)認識事務

假設表T只有一條記錄,值是1。我們來看看在不同的隔離級別下,事務A會有哪些不同的返回結果,也就是圖裡面T4、T6、T8的返回值分別是什麼。

  • 若隔離級別是“讀未提交”, 則T4的值就是2。這時候事務B雖然還沒有提交,但是結果已經被A看到了。因此,T6、T8也都是2。
  • 若隔離級別是“讀提交”,則T4是1,T6的值是2。事務B的更新在提交後才能被A看到。所以, T8的值也是2。
  • 若隔離級別是“可重複讀”,則T4、T6是1,T8是2。之所以T6還是1,遵循的就是這個要求:事務在執行期間看到的資料前後必須是一致的。
  • 若隔離級別是“序列化”,則在事務B執行“將1改成2”的時候,會被鎖住。直到事務A提交後,事務B才可以繼續執行。所以從A的角度看, T4、T6值是1,T8的值是2。

引數資料

相關文章