事務的acid理解

簡介

 

    ACID,是指在可靠數據庫管理系統(DBMS)中,事務(transaction)所應該具備的四個特性:原子性(Atomicity)、一致性 (Consistency)、隔離性(Isolation)、持久性(Durability).這是可靠數據庫所應具有的幾個特性.下面針對這幾個特性進 行逐個講解.數據庫

理解原子性(Atomicity)

   原子性意味着數據庫中的事務執行是做爲原子。即不可再分,整個語句要麼執行,要麼不執行。緩存

   在SQL SERVER中,每個單獨的語句均可以看做是默認包含在一個事務之中:服務器

 

因此,每個語句自己具備原子性,要麼所有執行,這麼所有不執行,不會有中間狀態: 
性能

 

 

上面說了,每一條T-SQL語句均可以看做是默認被包裹在一個事務之中的,SQL Server對於每一條單獨的語句都實現了原子性,但這種原子粒度是很是小的,若是用戶想要本身定義原子的大小,則須要包含在事務中來構成用戶自定義的原子粒度: 
spa

 

 

對 於用戶來講,要用事務實現的自定義原子性每每是和業務相關的,好比銀行轉帳,從A帳戶減去100,在B帳戶增長100,若是這兩個語句不能保證原子性的 話,好比從A帳戶減去100後,服務器斷電,而在B帳戶中卻沒有增長100.雖然這種狀況會讓銀行很開心,但做爲開發人員的你可不但願這種結果.而默認事 務中,即便出錯了也不會整個事務進行回滾。而是失敗的語句拋出異常,而正確的語句成功執行。這樣會破壞原子性。因此SQL SERVER給予了一些選項來保證事務的原子性.日誌

    SQL SERVER提供了兩大類方式來保證自定義事務的原子性:orm

  1.經過SET XACT_ABORT ON來設置事務必須符合原子性進程

       利用設置XACT_ABORT選項設置爲ON,來設置全部事務都做爲一個原子處理.下面例子利用兩個語句插入到數據庫,能夠看到開啓SET XACT_ABORT ON選項後,事務具備了原子性: 事務

 

 

2.按照用戶設置進行回滾(ROLLBACK)ci

       這種方式具備更高的靈活性,開發人員能夠自定義在什麼狀況進行ROLLBACK,利用TRY CATCH語句和@@ERROR進行判斷都屬於這種方式. 

 

 

理解一致性(Consistency)

     一致性,即在事務開始以前和事務結束之後,數據庫的完整性約束沒有被破壞。

     一致性分爲兩個層面

    1.數據庫機制層面

      數據庫層面的一致性是,在一個事務執行以前和以後,數據會符合你設置的約束(惟一約束,外鍵約束,Check約束等)和觸發器設置.這一點是由SQL SERVER進行保證的.

 

     2.業務層面

      對於業務層面來講,一致性是保持業務的一致性.這個業務一致性須要由開發人員進行保證.不少業務方面的一致性能夠經過轉移到數據庫機制層面進行保證.好比,產品只有兩個型號,則能夠轉移到使用CHECK約束使某一列必須只能存這兩個型號.

     

理解隔離性(Isolation)

    隔離性。事務的執行是互不干擾的,一個事務不可能看到其餘事務運行時,中間某一時刻的數據。

    在Windows中,若是多個進程對同一個文件進行修改是不容許的,Windows經過這種方式來保證不一樣進程的隔離性

 

 而SQL Server中,經過SQL SERVER對數據庫文件進行管理,從而可讓多個進程能夠同時訪問數據庫:

 SQL Server利用加鎖和阻塞來保證事務之間不一樣等級的隔離性.

    通常狀況下,徹底的隔離性是不現實的,徹底的隔離性要求數據庫同一時間只執行一條事務,這樣的性能可想而知.想要理解SQL Server中對於隔離性的保障,首先要了解事務之間是如何幹擾的.

    事務之間的互相影響的狀況分爲幾種,分別爲:髒讀(Dirty Read),不可重複讀,幻讀

 

髒讀

    髒讀意味着一個事務讀取了另外一個事務未提交的數據,而這個數據是有可能回滾的,下面來看一個例子:

     兩個事務,事務A插入一條數據,但未提交,事務B在此期間進行了讀取,讀取到了事務A未提交的數據,形成髒讀

 

 

不可重複讀(Unrepeatable Read)

     不可重複讀意味着,在數據庫訪問中,一個事務範圍內兩個相同的查詢卻返回了不一樣數據。這是因爲查詢時系統中其餘事務修改的提交而引發的。 

 下面來看一個不可重複讀的例子:

     事務B中對某個查詢執行兩次,當第一次執行完時,事務A對其數據進行了修改。事務B中再次查詢時,數據發生了改變:

 

幻讀(phantom read)

     幻讀,是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,這種修改涉及到表中的所有數據行。同時,第二個事務也修改 這個表中的數據,這種修改是向表中插入一行新數據。那麼,之後就會發生操做第一個事務的用戶發現表中還有沒有修改的數據行,就好象發生了幻覺同樣. 

 下面來看一個例子:

      事務B更新表中全部的數據,在此期間事務A插入了一條數據,事務B再次查詢後,發現竟然還有沒有修改的數據,產生幻讀:

 

 理解SQL SERVER中的隔離級別

     爲 了避免上述幾種事務之間的影響,SQL Server經過設置不一樣的隔離等級來進行不一樣程度的避免。由於高的隔離等級意味着更多的鎖,從而犧牲性能.因此這個選項開放給了用戶根據具體的需求進行 設置。不過默認的隔離等級Read Commited符合了99%的實際需求.

    SQL Server隔離事務之間的影響是經過鎖來實現的,這個概念比較繁雜,因此本文不會詳細對這個概念進行講解.經過阻塞來阻止上述效果

    SQL Server提供了5種選項來避免不一樣級別的事務之間的影響

    隔離等級由低到高分別爲

    Read Uncommited(最高的性能,但可能出現髒讀,不可重複讀,幻讀)

    Read commited(可能出現不可重複讀,幻讀)

    Repeatable Read(可能出現幻讀)

    Serializable(最低的性能,一次只能執行一個事務,但避免了上述全部狀況)

    SNOPSHOT(這個是經過在tempDB中建立一個額外的副原本避免髒讀,不可重複讀,會給tempDB形成額外負擔,由於不是標準ANSI SQL標準,不詳細討論)

 

    總之,不一樣的隔離級別是經過加不一樣的鎖,形成阻塞來實現的,來看一個例子:

    SQL SERVER經過阻塞來阻止髒讀,因此保持獨立性會以付出性能做爲代價:

 

 理解持久性(Durability)

     持久性,意味着在事務完成之後,該事務所對數據庫所做的更改便持久的保存在數據庫之中,並不會被回滾。

     即便出現了任何事故好比斷電等,事務一旦提交,則持久化保存在數據庫中.

     SQL SERVER經過write-ahead transaction log來保證持久性。write-ahead transaction log的意思是,事務中對數據庫的改變在寫入到數據庫以前,首先寫入到事務日誌中。而事務日誌是按照順序排號的(LSN)。當數據庫崩潰或者服務器斷點 時,重啓動SQL SERVER,SQL SERVER首先會檢查日誌順序號,將本應對數據庫作更改而未作的部分持久化到數據庫,從而保證了持久性.

 "若 要了解預寫日誌的工做原理,最重要的是瞭解如何將修改的數據寫入磁盤。SQL Server 維護當必須檢索數據時,將數據頁讀入的緩衝區高速緩存。數據修改不是直接在磁盤上進行,而是修改高速緩衝存儲器中的頁副本。直到數據庫中出現檢查點,或者 必須將修改寫入磁盤才能使用緩衝區來容納新頁時,纔將修改寫入磁盤。將修改後的數據頁從高速緩衝存儲器寫入磁盤的操做稱爲刷新頁。在高速緩存中修改但還沒有 寫入磁盤的頁稱爲「髒頁」。

對 緩衝區中的頁進行修改時,將在記錄修改的日誌高速緩存中生成一條日誌記錄。在將關聯的髒頁從高速緩衝存儲器刷新到磁盤以前,必須將這條日誌記錄寫入磁盤。 若是在寫入日誌記錄前刷新髒頁,則該髒頁便會在磁盤上建立修改。若是服務器在將日誌記錄寫入磁盤前失敗,則不能回滾此修改。SQL Server 具備防止在寫入關聯的日誌記錄前刷新髒頁的邏輯。日誌記錄將在提交事務時寫入磁盤。"(MSDN)

總結

    本文簡單講述了ACID的概念和ACID在SQL SERVER中的實現.ACID只是一個理念,並非某項具體的技術.對於健壯數據庫來講,保證ACID是可靠數據庫的前提.

相關文章
相關標籤/搜索