1. 程式人生 > >資料庫事務機制

資料庫事務機制

什麼是事務:
    事務(Transaction)是併發控制的單位,是使用者定義的一個操作序列。這些操作要麼都做,要麼都不做,是一個不可分割的工作單位。
    通過事務,SQL Server能將邏輯相關的一組操作繫結在一起,以便伺服器保持資料的完整性。
    (當我們需要執行多個sql語句,我們需要用事務操作,保證sql要麼全部成功,要麼全部失敗)


事務是怎麼實現的?

https://blog.csdn.net/DuTianTian_csdn/article/details/82711094
    藉助::
    undo log:(記錄之前的值)
        在操作任何資料之前,首先將資料備份到一個地方(這個儲存資料備份的地方成為undo log)。
    redo_log:(記錄之後的值)
        和undo log相反,redo log記錄的是新資料的備份。在事務提交前,只要將redo log持久化即可,
        不需要將資料持久化。當系統崩潰時,雖然資料沒有持久化,但是redo log已經持久化。系統可以根據
        redo log的內容,將所有資料恢復到最新的狀態。

事務執行步驟:
    事務通常是以BEGIN TRANSACTION開始,以COMMIT或ROLLBACK結束。
    COMMIT表示提交,即提交事務的所有操作。具體地說就是將事務中所有對資料庫的更新寫回到磁碟上的物理資料庫中去,事務正常結束。
    ROLLBACK表示回滾,即在事務執行的過程中發生了某種故障,事務不能繼續進行,系統將事務中對資料庫的所有以完成的操作全部撤消,滾回到事務開始的狀態。
 

資料庫的四大屬性

  • 原性性(Actomicity):事務是一個原子操作單元,其對資料的修改,要麼全都執行,要麼全都不執行。
  • 一致性(Consistent):在事務開始和完成時,資料都必須保持一致狀態。這意味著所有相關的資料規則都必須應用於事務的修改,以操持完整性;事務結束時,所有的內部資料結構(如B樹索引或雙向連結串列)也都必須是正確的。
  • 隔離性(Isolation):資料庫系統提供一定的隔離機制,保證事務在不受外部併發操作影響的“獨立”環境執行。這意味著事務處理過程中的中間狀態對外部是不可見的,反之亦然。
  • 永續性(Durable):事務完成之後,它對於資料的修改是永久性的,即使出現系統故障也能夠保持。  

事務併發排程的問題

  1. 髒讀(dirty read):A事務讀取B事務尚未提交的更改資料,並在這個資料基礎上操作。如果B事務回滾,那麼A事務讀到的資料根本不是合法的,稱為髒讀。在oracle中,由於有version控制,不會出現髒讀。
  2. 不可重複讀(unrepeatable read):A事務讀取了B事務已經提交的更改(或刪除)資料。比如A事務第一次讀取資料,然後B事務更改該資料並提交,A事務再次讀取資料,兩次讀取的資料不一樣。
  3. 幻讀(phantom read):A事務讀取了B事務已經提交的新增資料。注意和不可重複讀的區別,這裡是新增,不可重複讀是更改(或刪除)。這兩種情況對策是不一樣的,對於不可重複讀,只需要採取行級鎖防止該記錄資料被更改或刪除,然而對於幻讀必須加表級鎖,防止在這個表中新增一條資料。
  4. 第一類丟失更新:A事務撤銷時,把已提交的B事務的資料覆蓋掉。
  5. 第二類丟失更新:A事務提交時,把已提交的B事務的資料覆蓋掉。

  三級封鎖協議

  1. 一級封鎖協議:事務T中如果對資料R有寫操作,必須在這個事務中對R的第一次讀操作前對它加X鎖,直到事務結束才釋放。事務結束包括正常結束(COMMIT)和非正常結束(ROLLBACK)。
  2. 二級封鎖協議:一級封鎖協議加上事務T在讀取資料R之前必須先對其加S鎖,讀完後方可釋放S鎖。 
  3. 三級封鎖協議 :一級封鎖協議加上事務T在讀取資料R之前必須先對其加S鎖,直到事務結束才釋放。

  可見,三級鎖操作一個比一個厲害(滿足高階鎖則一定滿足低階鎖)。但有個非常致命的地方,一級鎖協議就要在第一次讀加x鎖,直到事務結束。幾乎就要在整個事務加寫鎖了,效率非常低。三級封鎖協議只是一個理論上的東西,實際資料庫常用另一套方法來解決事務併發問題。

  隔離性級別

  mysql用意向鎖(另一種機制)來解決事務併發問題,為了區別封鎖協議,弄了一個新概念隔離性級別:包括Read Uncommitted、Read Committed、Repeatable Read、Serializable,見這篇。mysql 一般預設Repeatable Read。

   

  

  終於發現自己為什麼會誤會事務能解決丟失修改了。至於為什麼隔離性級別不解決丟失修改,我猜是有更好的解決方案吧。

  總結一下,repeatable read能解決髒讀和不可重複讀,但不嗯呢該解決丟失修改。