ACID學習記錄

數據庫事務ACID

下面是從網上整理來的:數據庫

原子性

不管一個事務裏有多少執行步驟,這全部的步驟合起來是一個最小的執行單元,要麼不作,要麼全作,不存在只作到一半狀況。好比銀行轉帳,轉出跟轉入這兩個包含在一個事務裏的動做就是原子的。要麼不轉出也不轉入,轉出了就要轉入。併發

一致性

事務執行前與執行後數據內在的邏輯始終是成立的。好比轉帳前與轉帳後兩人存款的總和始終不變。性能

隔離性

雖然說事務是原子的,要麼不作,要麼全作,不存在作一半的狀況。可是從代碼實現上來講,事務裏的步驟仍是一步一步執行的,仍是存在事務作到一半的狀況。好比轉帳,代碼怎麼寫?就兩行代碼,是先轉出扣錢,再轉入加錢。兩行代碼中間,也就是轉出以後,轉入以前,此時數據是不一致的。那怎樣始終保證數據一致?那就用一個相似自欺欺人的辦法,讓轉帳這個事務在完成以前對別人都不可見,事務完成以前別人看到的都是轉帳前的狀態,看不到轉帳步驟中間不一致的狀態,所謂」隔離」。.net

實際中,一個事務會不會讀取到另外一個未提交的事務修改的數據,這個就是互相影響的程度。在事務併發操做時,可能出現的問題有:code

  1. 髒讀:(針對未提交數據),若是一個事務中對數據進行了更新,但事務尚未提交,另外一個事務能夠「看到」該事務沒有提交的更新結果,這樣形成的問題就是,若是第一個事務回滾,那麼,第二個事務在此以前所「看到」的數據就是一筆髒數據。blog

  2. 不可重複讀:(針對其餘提交先後,讀取數據自己的對比),**不可重複讀取是指同一個事務在整個事務過程當中對同一筆數據進行讀取,每次讀取結果都不一樣。**若是事務1在事務2的更新操做以前讀取一次數據,在事務2的更新操做以後再讀取同一筆數據一次,兩次結果是不一樣的,因此,Read Uncommitted也沒法避免不可重複讀取的問題。不可重複讀出現的緣由就是事務併發修改記錄,要避免這種狀況,最簡單的方法就是對要修改的記錄加鎖,這回致使鎖競爭加重,影響性能。另外一種方法是經過MVCC能夠在無鎖的狀況下,避免不可重複讀。事務

例子: 在事務1中,Mary 讀取了本身的工資爲1000,操做並無完成 代碼:get

con1 = getConnection();
select salary from employee empId ="Mary";

在事務2中,這時財務人員修改了Mary的工資爲2000,並提交了事務. 代碼:博客

con2 = getConnection();
update employee set salary = 2000;
con2.commit();

在事務1中,Mary 再次讀取本身的工資時,工資變爲了2000 代碼it

//con1  
select salary from employee empId ="Mary";

在一個事務中先後兩次讀取的結果並不致,致使了不可重複讀。

  1. 幻讀:(針對其餘提交先後,讀取數據條數的對比),**幻讀是指一樣一筆查詢在整個事務過程當中屢次執行後,查詢所得的結果集是不同的。**幻讀針對的是多筆記錄。在Read Uncommitted隔離級別下, 無論事務2的插入操做是否提交,事務1在插入操做以前和以後執行相同的查詢,取得的結果集是不一樣的,因此,Read Uncommitted一樣沒法避免幻讀的問題。 ~幻讀是因爲併發事務增長記錄致使的~ ,這個不能像不可重複讀經過記錄加鎖解決,由於對於新增的記錄根本沒法加鎖。須要將事務串行化,才能避免幻讀。

事務的隔離級別從低到高有:

  1. Read Uncommitted:最低的隔離級別,什麼都不須要作,一個事務能夠讀到另外一個事務未提交的結果。全部的併發事務問題都會發生。
  2. Read Committed:只有在事務提交後,其更新結果纔會被其餘事務看見。能夠解決髒讀問題。
  3. Repeated Read:在一個事務中,對於同一份數據的讀取結果老是相同的,不管是否有其餘事務對這份數據進行操做,以及這個事務是否提交。能夠解決髒讀、不可重複讀。
  4. Serialization:事務串行化執行,隔離級別最高,犧牲了系統的併發性。能夠解決併發事務的全部問題。 一般,在工程實踐中,爲了性能的考慮會對隔離性進行折中。

持久性

事務提交後,對系統的影響是永久的。就像錢轉給別人後當前這比轉帳交易就結束了,不可能再倒回來。

如何理解數據庫事務中的一致性的概念? - 知乎
對於髒讀,不可重複讀,幻讀的一點理解,看懂紅字很關鍵 - 有志者事竟成 - CSDN博客

相關文章
相關標籤/搜索