數據庫:事務的併發?事務隔離級別?嵌套事務?事務傳播行為?

事務是對數據庫中一系列操作進行統一的回滾或者提交的操作,主要用來保證數據的完整性和一致性。

l 事務四大特性(ACID)原子性、一致性、隔離性、持久性?

原子性(Atomicity):

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

一致性(Consistency):

事務開始前和結束後,數據庫的完整性約束沒有被破壞。比如A向B轉賬,不可能A扣了錢,B卻沒收到。

隔離性(Isolation):

隔離性是當多個用戶併發訪問數據庫時,比如操作同一張表時,數據庫為每一個用戶開啟的事務,不能被其他事務的操作所幹擾,多個併發事務之間要相互隔離。同一時間,只允許一個事務請求同一數據,不同的事務之間彼此沒有任何干擾。比如A正在從一張銀行卡中取錢,在A取錢的過程結束前,B不能向這張卡轉賬。

持久性(Durability):

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

事務的併發?事務隔離級別,每個級別會引發什麼問題,MySQL默認是哪個級別?

從理論上來說, 事務應該彼此完全隔離, 以避免併發事務所導致的問題,然而, 那樣會對性能產生極大的影響, 因為事務必須按順序運行, 在實際開發中, 為了提升性能, 事務會以較低的隔離級別運行, 事務的隔離級別可以通過隔離事務屬性指定。

事務的併發問題

1、髒讀:事務A讀取了事務B更新的數據,然後B回滾操作,那麼A讀取到的數據是髒數據;

2、不可重複讀:事務 A 多次讀取同一數據,事務 B 在事務A多次讀取的過程中,對數據作了更新並提交,導致事務A多次讀取同一數據時,結果因此本事務先後兩次讀到的數據結果會不一致。

3、幻讀:幻讀解決了不重複讀,保證了同一個事務裡,查詢的結果都是事務開始時的狀態(一致性)。

例如:事務T1對一個表中所有的行的某個數據項做了從“1”修改為“2”的操作 這時事務T2又對這個表中插入了一行數據項,而這個數據項的數值還是為“1”並且提交給數據庫。 而操作事務T1的用戶如果再查看剛剛修改的數據,會發現還有跟沒有修改一樣,其實這行是從事務T2中添加的,就好像產生幻覺一樣,這就是發生了幻讀。

小結:不可重複讀的和幻讀很容易混淆,不可重複讀側重於修改,幻讀側重於新增或刪除。解決不可重複讀的問題只需鎖住滿足條件的行,解決幻讀需要鎖表。

事務的隔離級別

  • l 讀未提交:另一個事務修改了數據,但尚未提交,而本事務中的SELECT會讀到這些未被提交的數據髒讀
  • l 不可重複讀:事務 A 多次讀取同一數據,事務 B 在事務A多次讀取的過程中,對數據作了更新並提交,導致事務A多次讀取同一數據時,結果因此本事務先後兩次讀到的數據結果會不一致。
  • l 可重複讀:在同一個事務裡,SELECT的結果是事務開始時時間點的狀態,因此,同樣的SELECT操作讀到的結果會是一致的。但是,會有幻讀現象
  • l 串行化:最高的隔離級別,在這個隔離級別下,不會產生任何異常。併發的事務,就像事務是在一個個按照順序執行一樣

特別注意:

l MySQL默認的事務隔離級別為repeatable-read

l MySQL 支持 4 中事務隔離級別.

l 事務的隔離級別要得到底層數據庫引擎的支持, 而不是應用程序或者框架的支持.

l Oracle 支持的 2 種事務隔離級別:READ_COMMITED , SERIALIZABLE

l SQL規範所規定的標準,不同的數據庫具體的實現可能會有些差異

l MySQL中默認事務隔離級別是“可重複讀”時並不會鎖住讀取到的行

l 事務隔離級別:未提交讀時,寫數據只會鎖住相應的行。

l 事務隔離級別為:可重複讀時,寫數據會鎖住整張表。

l 事務隔離級別為:串行化時,讀寫數據都會鎖住整張表。

l 隔離級別越高,越能保證數據的完整性和一致性,但是對併發性能的影響也越大,魚和熊掌不可兼得啊。對於多數應用程序,可以優先考慮把數據庫系統的隔離級別設為Read Committed,它能夠避免髒讀取,而且具有較好的併發性能。儘管它會導致不可重複讀、幻讀這些併發問題,在可能出現這類問題的個別場合,可以由應用程序採用悲觀鎖或樂觀鎖來控制。

事務傳播行為

[ˌprɒpə'ɡeɪʃ(ə)n]

1. propagation_required:[rɪˈkwaɪəd]如果當前沒有事務,就創建一個新事務,如果當前存在事務,就加入該事務,該設置是最常用的設置。

2. propagation_ supports:[səˈpɔːts]支持當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就以非事務執行。

3. propagation_ mandatory:[ˈmændətəri]支持當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就拋出異常。

4. propagation_requires_NEW:

創建新事務,無論當前存不存在事務,都創建新事務。

5. propagation_NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。

6. propagation_ never:以非事務方式執行,如果當前存在事務,則拋出異常。

7. propagation_ nested:[ˈnestɪd]如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。

嵌套事務

l 什麼是嵌套事務?

l 嵌套是子事務套在父事務中執行,子事務是父事務的一部分,在進入子事務之前,父事務建立一個回滾點,叫save point,然後執行子事務,這個子事務的執行也算是父事務的一部分,然後子事務執行結束,父事務繼續執行。重點就在於那個save point。看幾個問題就明瞭了:

l 如果子事務回滾,會發生什麼?

l 父事務會回滾到進入子事務前建立的save point,然後嘗試其他的事務或者其他的業務邏輯,父事務之前的操作不會受到影響,更不會自動回滾。

l 如果父事務回滾,會發生什麼?

l 父事務回滾,子事務也會跟著回滾!為什麼呢,因為父事務結束之前,子事務是不會提交的,我們說子事務是父事務的一部分,正是這個道理。那麼:

l 事務的提交,是什麼情況?

l 是父事務先提交,然後子事務提交,還是子事務先提交,父事務再提交?答案是第二種情況,還是那句話,子事務是父事務的一部分,由父事務統一提交。


分享到:


相關文章: