一.事務sql
定義:所謂事務,它是一個操做序列,這些操做要麼都執行,要麼都不執行,它是一個不可分割的工做單位。數據庫
準備工做:爲了說明事務的ACID原理,咱們使用銀行帳戶及資金管理的案例進行分析。安全
[sql] view plain copy服務器
二.ACID多線程
ACID,是指在可靠數據庫管理系統(DBMS)中,事務(transaction)所應該具備的四個特性:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability).這是可靠數據庫所應具有的幾個特性.下面針對這幾個特性進行逐個講解.併發
三.原子性app
原子性是指事務是一個不可再分割的工做單位,事務中的操做要麼都發生,要麼都不發生。性能
1.案例spa
A給B轉賬100元錢.net
[sql] view plain copy
2.分析
在事務中的扣款和加款兩條語句,要麼都執行,要麼就都不執行。不然若是隻執行了扣款語句,就提交了,此時若是忽然斷電,A帳號已經發生了扣款,B帳號卻沒收到加款,在生活中就會引發糾紛。
3.解決方法
在數據庫管理系統(DBMS)中,默認狀況下一條SQL就是一個單獨事務,事務是自動提交的。只有顯式的使用start transaction開啓一個事務,才能將一個代碼塊放在事務中執行。保障事務的原子性是數據庫管理系統的責任,爲此許多數據源採用日誌機制。例如,SQL Server使用一個預寫事務日誌,在將數據提交到實際數據頁面前,先寫在事務日誌上。
四.一致性
一致性是指在事務開始以前和事務結束之後,數據庫的完整性約束沒有被破壞。這是說數據庫事務不能破壞關係數據的完整性以及業務邏輯上的一致性。
1.案例
對銀行轉賬事務,無論事務成功仍是失敗,應該保證事務結束後ACCOUNT表中aaa和bbb的存款總額爲2000元。
2.解決方法
保障事務的一致性,能夠從如下兩個層面入手
2.1數據庫機制層面
數據庫層面的一致性是,在一個事務執行以前和以後,數據會符合你設置的約束(惟一約束,外鍵約束,Check約束等)和觸發器設置。這一點是由SQL SERVER進行保證的。好比轉帳,則可使用CHECK約束兩個帳戶之和等於2000來達到一致性目的
2.2業務層面
對於業務層面來講,一致性是保持業務的一致性。這個業務一致性須要由開發人員進行保證。固然,不少業務方面的一致性,也能夠經過轉移到數據庫機制層面進行保證。
五.隔離性
多個事務併發訪問時,事務之間是隔離的,一個事務不該該影響其它事務運行效果。
這指的是在併發環境中,當不一樣的事務同時操縱相同的數據時,每一個事務都有各自的完整數據空間。由併發事務所作的修改必須與任何其餘併發事務所作的修改隔離。事務查看數據更新時,數據所處的狀態要麼是另外一事務修改它以前的狀態,要麼是另外一事務修改它以後的狀態,事務不會查看到中間狀態的數據。
在Windows中,若是多個進程對同一個文件進行修改是不容許的,Windows經過這種方式來保證不一樣進程的隔離性:
企業開發中,事務最複雜問題都是由事務隔離性引發的。當多個事務併發時,SQL Server利用加鎖和阻塞來保證事務之間不一樣等級的隔離性。通常狀況下,徹底的隔離性是不現實的,徹底的隔離性要求數據庫同一時間只執行一條事務,這樣會嚴重影響性能。想要理解SQL Server中對於隔離性的保障,首先要了解併發事務之間是如何幹擾的.
1.事務之間的相互影響
事務之間的相互影響分爲幾種,分別爲:髒讀,不可重複讀,幻讀,丟失更新
1.1髒讀
髒讀意味着一個事務讀取了另外一個事務未提交的數據,而這個數據是有可能回滾的;以下案例,此時若是事務1回滾,則B帳戶必將有損失。
1.2不可重複讀
不可重複讀意味着,在數據庫訪問中,一個事務範圍內兩個相同的查詢卻返回了不一樣數據。這是因爲查詢時系統中其餘事務修改的提交而引發的。以下案例,事務1必然會變得糊塗,不知道發生了什麼。
1.3幻讀(虛讀)
幻讀,是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,這種修改涉及到表中的所有數據行。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那麼,之後就會發生操做第一個事務的用戶發現表中還有沒有修改的數據行,就好象發生了幻覺同樣.
1.4丟失更新
兩個事務同時讀取同一條記錄,A先修改記錄,B也修改記錄(B是不知道A修改過),B提交數據後B的修改結果覆蓋了A的修改結果。
2.理解SQL SERVER中的隔離級別
數據庫的事務隔離級別(TRANSACTION ISOLATION LEVEL)是一個數據庫上很基本的一個概念。爲何會有事務隔離級別,SQL Server上實現了哪些事務隔離級別?事務隔離級別的前提是一個多用戶、多進程、多線程的併發系統,在這個系統中爲了保證數據的一致性和完整性,咱們引入了事務隔離級別這個概念,對一個單用戶、單線程的應用來講則不存在這個問題。
爲了不上述幾種事務之間的影響,SQL Server經過設置不一樣的隔離級別來進行不一樣程度的避免。由於高的隔離等級意味着更多的鎖,從而犧牲性能。因此這個選項開放給了用戶根據具體的需求進行設置。不過默認的隔離級別Read Commited符合了多數的實際需求.
隔離級別 |
髒讀 |
丟失更新 |
不可重複讀 |
幻讀 |
併發模型 |
更新衝突檢測 |
未提交讀:Read Uncommited |
是 |
是 |
是 |
是 |
悲觀 |
否 |
已提交讀:Read commited |
否 |
是 |
是 |
是 |
悲觀 |
否 |
可重複讀:Repeatable Read |
否 |
否 |
否 |
是 |
悲觀 |
否 |
可串行讀:Serializable |
否 |
否 |
否 |
否 |
悲觀 |
否 |
SQL Server隔離事務之間的影響是經過鎖來實現的,經過阻塞來阻止上述影響。不一樣的隔離級別是經過加不一樣的鎖,形成阻塞來實現的,因此會以付出性能做爲代價;安全級別越高,處理效率越低;安全級別越低,效率高。
使用方法:SET TRANSACTIONISOLATION LEVEL REPEATABLE READ
未提交讀: 在讀數據時不會檢查或使用任何鎖。所以,在這種隔離級別中可能讀取到沒有提交的數據。
已提交讀:只讀取提交的數據並等待其餘事務釋放排他鎖。讀數據的共享鎖在讀操做完成後當即釋放。已提交讀是SQL Server的默認隔離級別。
可重複讀: 像已提交讀級別那樣讀數據,但會保持共享鎖直到事務結束。
可串行讀:工做方式相似於可重複讀。但它不只會鎖定受影響的數據,還會鎖定這個範圍。這就阻止了新數據插入查詢所涉及的範圍。
六.持久性
持久性,意味着在事務完成之後,該事務所對數據庫所做的更改便持久的保存在數據庫之中,並不會被回滾。
即便出現了任何事故好比斷電等,事務一旦提交,則持久化保存在數據庫中。
SQL SERVER經過write-ahead transaction log來保證持久性。write-ahead transaction log的意思是,事務中對數據庫的改變在寫入到數據庫以前,首先寫入到事務日誌中。而事務日誌是按照順序排號的(LSN)。當數據庫崩潰或者服務器斷點時,重啓動SQL SERVER,SQLSERVER首先會檢查日誌順序號,將本應對數據庫作更改而未作的部分持久化到數據庫,從而保證了持久性。
七.總結
事務的(ACID)特性是由關係數據庫管理系統(RDBMS,數據庫系統)來實現的。數據庫管理系統採用日誌來保證事務的原子性、一致性和持久性。日誌記錄了事務對數據庫所作的更新,若是某個事務在執行過程當中發生錯誤,就能夠根據日誌,撤銷事務對數據庫已作的更新,使數據庫退回到執行事務前的初始狀態。
數據庫管理系統採用鎖機制來實現事務的隔離性。當多個事務同時更新數據庫中相同的數據時,只容許持有鎖的事務能更新該數據,其餘事務必須等待,直到前一個事務釋放了鎖,其餘事務纔有機會更新該數據。