簡單的大白話聊一聊數據庫事務的特性ACID,重點介紹隔離級別

本篇講一下數據庫中事務的四大特性(ACID),並且將會詳細地說明事務的隔離級別。

⑴ 原子性(Atomicity)

  原子性是指事務包含的所有操作要麼全部成功,要麼全部失敗回滾,因此事務的操作如果成功就必須要完全應用到數據庫,如果操作失敗則不能對數據庫有任何影響。

⑵ 一致性(Consistency)

  一致性是指事務必須使數據庫從一個一致性狀態變換到另一個一致性狀態,也就是說一個事務執行之前和執行之後都必須處於一致性狀態。

  舉個簡單的栗子,拿轉賬來說,假設用戶A和用戶B兩者的錢加起來一共是5000,那麼不管A和B之間如何轉賬,轉幾次賬,事務結束後兩個用戶的錢相加起來應該還得是5000,這就是事務的一致性。

⑶ 隔離性(Isolation)

  隔離性是當多個用戶併發訪問數據庫時,比如操作同一張表時,數據庫爲每一個用戶開啓的事務,每個不能被其他事務的操作所幹擾,多個併發事務之間要相互隔離。

即要達到這麼一種效果:對於任意兩個併發的事務T1和T2,在事務T1看來,T2要麼在T1開始之前就已經結束,要麼在T1結束之後纔開始,這樣每個事務都感覺不到有其他事務在併發地執行。

關於事務的隔離性數據庫提供了多種隔離級別,下面會重點介紹。

⑷ 持久性(Durability)

  持久性是指一個事務一旦被提交了,那麼對數據庫中的數據的改變就是永久性的,即便是在數據庫系統遇到故障的情況下也不會丟失提交事務的操作。

  例如我們在使用JDBC操作數據庫時,在提交事務方法後,提示用戶事務操作完成,當我們程序執行完成直到看到提示後,就可以認定事務以及正確提交,即使這時候數據庫出現了問題,也必須要將我們的事務完全執行完成,否則就會造成我們看到提示事務處理完畢,但是數據庫因爲故障而沒有執行事務的重大錯誤。

 

重點說一下事務的隔離性

如果沒有事務的隔離性容易出現的情況:

1.髒讀:  在一個事務中讀到另一個事務未提交的更新數據。
 
2.不可重複讀:  在一個事務中讀到了另一個事務提交的更新數據化。針對記錄的(即一行),在一個事務中同一條記錄前後讀到的數據不一致。簡單說就是同一個事務內前後讀兩次數據,第二次有可能會讀到其他事務提交過來的更新數據,造成前後兩次讀的數據不一致。舉個例子,就是第一次讀的時候,另外一個事務還沒提交,但是第二次讀的時候另外一個事務的更新數據提交了,而且提交的數據被你這個事務讀到了,就造成了前後兩次讀到的數據不一致。正常情況下只要在我這個事務內,不管什麼時候讀數據都應該一致,不應該受其他事務的影響
 
3.虛讀(幻讀): 在一個事務中讀到了另一個事務提交的新插入數據。如果符合搜索條件的一行數據在後面的讀取操作中出現,但該行數據卻不屬於最初的數據,就會發生這種事件。(加顏色部分是官方的解釋)。下邊是自己的理解:虛度針對表的,在同一個事務中用相同的搜索條件查同一張表的數據,比如第一次查到5條,但是第二次再用相同的查詢條件去查,查到了6條,前後讀到的記錄數不一致,這就是虛度也叫幻讀
 
關於髒讀、不可重複讀和幻讀的個人理解:
髒讀:是在一個事務(當前事務)中,另一個事務未提交的更新數據,被當前事務感知到了;
不可重複讀:是在一個事務(當前事務)中,另外一個事務提交的更新數據或提交的刪除數據,被當前的事務感知到了;
幻讀:是在一個事務(當前事務)中,另外一個提交的新插入數據,被當前的事務感知到了。
說白了,不管是哪種情況都是一個正在進行中的事務受到了別的事務的影響,但是我們期望的是,一個事務一旦開始,那麼在這個事務執行的期間就不應該受其他事務影響(也就是在我這個事務的過程中,其他事務對數據進行的一些操作,都不應該讓我看到或者感知到)
 
針對這些容易出現的問題,數據庫設置了對應的事務隔離級別

1.未提交讀(read uncommitted):會出現髒讀、不可重複讀和幻讀,級別最低

2.提交讀(read committed):會出現不可重複讀和幻讀。oracle的默認事務隔離級別,也是大多數數據的默認級別

3.可重複讀(repeatable read):會出現幻讀,mysql默認級別

4.串行化(serializable):隔離級別最高,不允許出現髒讀、不可重複讀和幻讀。即一個事務執行結束了另一個事務才能執行,類似於Java中的synchronized加鎖,因爲是串行化的,所以在併發時性能也最差。

說明:雖然串行化是最安全的,但是現實生產環境中不一定都設置成這個級別,因爲雖然是最安全的,但是效率和性能不好。設置什麼樣的隔離級別比較合適得根據具體的業務需求定,不一定級別最高的就是最好的。
 
如果數據庫設置的隔離級別不滿足當前的業務需求時,你可以適當的修改,當然也可以不修改整個數據庫的事務隔離級別,用Java代碼來控制當前業務需求中的事務隔離級別。
 
Java中設置數據事務的隔離級別
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
conn.setAutoCommit(false);//開啓事務

 

其中Connection.TRANSACTION_READ_COMMITTED只是隔離級別中的一個只是舉個例子,其他的三種級別,java中也有對應的常量

注意:設置事務的隔離級別一定要在開啓事務之前進行設置

 

總結:上邊是自己對數據庫以及事務和隔離級別的一些簡單的理解,供大家參考,若有錯誤的地方希望大家包涵並及時指出,3Q~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章