數據庫的事務

今天是工做日的最後一天,明天就是除夕了,趕忙趁這個時間再寫一篇文章。今天主要說一下事務,這裏主要探討數據庫的事務機制,並非spring的事務,畢竟大多數人對spring的事務實際上是很清楚的。可是對於數據庫底層的事務瞭解的不是很深刻,每每有時候會遇到奇怪的現象,廢話很少說,直接開始!mysql

--------------------------------------------------華麗的分割線--------------------------------------------spring

首先事務有四個特性(ACID):原子性,一致性,隔離性,持久性。這些特性能夠保證多個數據庫事務併發執行時互不干擾,不會取到中間狀態的錯誤結果。通常的數據庫會給咱們設置多個事務隔離級別:Read uncommitted,Read committed,Repeatable read,Serializable。多個事務併發執行,若是說要保證操做一個接一個執行,那麼就要保證串行化,這個隔離級別是Serializable,通常來講咱們不多選擇這個事務隔離級別,併發量太差。咱們通常能夠採用鎖機制來實現,採用行鎖或者表鎖來完成。上面提到的都是寫事務,其實事務準確的來講應該分爲:讀事務和寫事務。在大多數業務當中,讀事務的比例是遠高於寫事務比例的,比例大概爲10:1,爲了提升讀事務的性能,數據庫通常採用COW(寫時複製),MVCC(多版本控制機制)來防止寫事務阻塞讀事務。sql

關於數據庫併發的解決方案主要有如下幾種:數據庫

一、鎖併發

若是兩個事務操做不一樣的行,那麼是行鎖級別的話就能夠互相不干擾;若是其中一個事務鎖行,另外一個事務鎖表,那麼就會致使其中一個等待;若是一個事務A執行須要先鎖A而後請求B鎖,另外一個事務鎖B而後請求A鎖,就會產生死鎖,這個通常設置一下事務超時時間就能夠解決。性能

二、COW版本控制

寫時複製其實很是常見,好比說JUC包下的copyonwritearraylist。原理就是當寫的時候不是直接在原數據上寫,而是複製一份新數據,在新數據上修改,而後原子的更換葉子指針的地址。當此時有讀操做的時候,若是讀操做在原子更換前,那麼讀的是舊數據,若是在更換後,那麼獲取的是新數據。這樣就保證了讀和寫的同時進行。指針

三、MVCC事務

多版本控制能夠說是最難掌握的,而且也是比較複雜的一種機制,mysql的innodb就比較經常使用這種機制。it

先來看一個圖:

其實在存儲數據的時候,會有兩個隱藏列,一個是數據更新時間,一個是數據刪除時間,固然這裏的時間都是版本號。當你開一個事務的時候,數據庫首先會給你一個自增的版本號,而後你帶着這個版本號就撈取數據。那麼會產生這麼一個規則:

(1)在select的時候,會撈取(數據修改版本號<=當前事務版本號)而且(刪除版本號沒有或者刪除版本號大於當前事務版本號)的行。

(2)insert操做致使update版本號爲當前事務版本號。

(3)update操做會首先複製一行而後修改,而且設置update版本號爲當前事務版本號。

(4)delete操做會致使delete版本號爲爲當前事務版本號,這裏只作一下標記。

因爲MVCC存儲了一個數據的多個版本,因此會按期刪除再也不須要的版本,及時回收空間。

 

對於上面的說明,舉一個例子:

假設mysql數據庫的隔離級別爲默認的(4:可重複讀),那麼必須保證一個事務的操做不會致使另外一個事務先後兩次讀取的數據不一致。

那麼MVCC機制如何解決這個問題?

首先假設第一個事務第一次讀取數據,此時第二個事務修改了第一個事務要讀取的數據,那麼這時候會產生新的一行,而且將其版本號設置爲最新的,那麼第一個事務再一次讀取數據的時候由於遵循了MVCC機制(掃描修改版本號小於等於當前事務版本號的行),就能夠保證兩次讀取的數據一致。

以上就是本章的介紹,順便祝你們新年快樂。

相關文章
相關標籤/搜索