數據庫事務概覽

事務種類

  • 隱式事務

    如單條 sql 語句的執行

  • 顯式事務

    如多條 sql 語句的執行,一般談論數據庫事務時,指的是數據庫的顯式事務

事務特性

數據庫事務具有 ACID 這4個特性

  • A —— Atomic /əˈtɒmɪk/

    原子性。所有 sql 作爲一個原子工作單元執行,要麼全部執行,要麼全部不執行。這裏應該是借用了化學學科的術語概念:原子雖然在物理狀態中可以繼續細分(原子由原子核和核外電子組成),但原子在化學反應中是不可再分。

  • C —— Consistent /kənˈsɪstənt/

    一致性。事務完成後,所有數據的狀態都是一致的,比如我轉賬給你100,那麼我的賬戶減去了100,你的賬戶則必定加上了100。

  • I —— Isolation /ˌaɪsəˈleɪʃn/

    隔離性。每個事務做的操作必須與其它事務隔離,即便有多個事務併發執行。一個事務處理時的中間狀態對其它事務是不可見的。

  • D —— Duration /duˈreɪʃn/

    持久性。事務完成後,相關的對數據庫數據的修改被持久化存儲。

數據不一致問題

多個併發執行的事務,如果操作時涉及同一條記錄數據,可能會發生問題,即併發操作可能導致數據的不一致問題,這些問題包含以下3種情形:

  • 髒讀(Dirty Read)

    讀取未提交數據

    執行時間 事務A 事務B
    1 事務開啓
    2 事務開啓 修改一條記錄record(假使原來數據是純粹乾淨的,被改了,就不純粹了,髒了)
    3 讀取事務B修改的那條記錄(事務B之後的事務回滾,導致了此時產生髒讀)
    4 事務回滾
    5 再次讀取事務B修改的那條記錄
    6 事務提交
  • 不可重複讀(Non Repeatable Read)

    前後多次讀取,數據內容不一致

    執行時間 事務A 事務B
    1 事務開啓
    2 讀取一條記錄record 事務開啓
    3 修改事務A讀取的那條記錄
    4 事務提交
    5 再次讀取這條記錄record(此時發現這條記錄跟在同一個事務內之前讀取的不一致了,不能重複讀)
    6 事務提交
  • 幻讀(Phantom Read)

    Phantom /ˈfæntəm/ ,前後多次讀取,數據記錄總數不一致

    執行時間 事務A 事務B
    1 事務開啓
    2 查詢記錄總數count
    3 事務開啓
    4 增加或刪除一些記錄
    5 事務提交
    6 再次查詢記錄總數count(此時count比原來的大了或小了,記錄總數變了,幻讀)
    7 事務提交

隔離級別

爲了避免(不是解決)上述可能出現的數據不一致問題,數據庫系統提供了隔離級別(Isolation Level)這一機制。
SQL標準定義了4種隔離級別:
1. Read Uncommitted (可以讀取未提交數據)
2. Read Committed(可以讀取已提交數據)
3. Repeatable Read(可重複讀)
4. Serializable(可串行化)
各種隔離級別分別對應可能出現的數據不一致的情況(Y標誌可能出現):

隔離級別(Isolation Level ) 髒讀(Dirty Read) 不可重複讀(Non Repeatable Read) 幻讀(Phantom Read)
Read Uncommitted Y Y Y
Read Committed - Y Y
Repeatable Read - - Y
Serializable - - -

隔離級別雙刃劍

Read Uncommitted、Read Committed、Repeatable Read、Serializable 這4種隔離級別,按隔離級別嚴格程度劃分,Read Uncommitted隔離級別最低,Serializable隔離級別最嚴,隔離級別越嚴格,安全性越高,越能保證數據的一致性,但對併發性能的影響也越大,所謂“魚與熊掌不可兼得”吧。例如,對於Serializable隔離級別,由於事務是串行執行,即所有事務按照次序依次執行,所以效率會大大下降,應用程序的性能會急劇降低。實際項目使用時需要權衡“利弊”,比如MySQL中的InnoDB引擎,其爲了兼顧安全與性能,默認的隔離級別就是Repeatable Read,然後採取隔離級別之外的措施來避免“幻讀”的問題。

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