MySQL(一)---事務

MySQL事務

#1 事務

事務(transaction)是作爲一個單元的一組有序的數據庫操作。如果組中的所有操作都成功,則認爲事務成功,即使只有一個操作失敗,事務也不成功。如果所有操作完成,事務則提交,其修改將作用於所有其他數據庫進程。如果一個操作失敗,則事務將回滾,該事務所有操作的影響都將取消。

#2 事務特性

一般來說,事務是必須滿足4個條件(ACID):原子性(Atomicity,或稱不可分割性)、一致性(Consistency)、隔離性(Isolation,又稱獨立性)、持久性(Durability)。

  • 原子性:一個事務(transaction)中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。
  • 一致性:在事務開始之前和事務結束以後,數據庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設規則,這包含資料的精確度、串聯性以及後續數據庫可以自發性地完成預定的工作。
  • 隔離性:數據庫允許多個併發事務同時對其數據進行讀寫和修改的能力,隔離性可以防止多個事務併發執行時由於交叉執行而導致數據的不一致。事務隔離分爲不同級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重複讀(repeatable read)和串行化(Serializable)。
  • 持久性:事務處理結束後,對數據的修改就是永久的,即便系統故障也不會丟失。

#3 MySQL隔離

#3.1 爲什麼需要設置隔離?

在數據庫操作中,在併發的情況下可能出現如下問題

  • 更新丟失(Lost update)
  • 髒讀(Dirty Reads)
  • 不可重複讀(Non-repeatable Reads)
  • 幻象讀

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ctJR8NqQ-1583433950250)(https://raw.githubusercontent.com/Coxhuang/yosoro/master/20200303161559-image.png)]

#3.1.1 更新丟失(Lost update)

當兩個事務選擇同一行,然後更新數據,由於每個事務都不知道其他事務的存在,就會發生丟失更新的問題,(你我同時讀取同一行數據,進行修改,你commit之後我也commit,那麼我的結果將會覆蓋掉你的結果)

事務A覆蓋事務B已經提交的數據,造成事務B所做的操作丟失。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HXQ91e6L-1583433950252)(https://raw.githubusercontent.com/Coxhuang/yosoro/master/20200226164822-image.png)]

解決方法:對行加鎖,只允許併發一個更新事務。

#3.1.2 髒讀(Dirty Reads)

一個事務正在對一條記錄做修改,在這個事務提交之前,別的事務讀取到了這個事務修改之後的數據,也就是說,一個事務讀取到了其他事務還沒有提交的數據,就叫做髒讀。

20200226165330-image.png

解決辦法:如果在第一個事務提交前,任何其他事務不可讀取其修改過的值,則可以避免該問題。

#3.1.3 不可重複讀(Non-repeatable Reads)

不可重複讀 就是一個事務讀到另一個事務修改後並提交的數據(update)。在同一個事務中,對於同一組數據讀取到的結果不一致。比如,事務B 在 事務A 提交前讀到的結果,和在 事務A 提交後讀到的結果可能不同。不可重複讀出現的原因就是由於事務併發修改記錄而導致的。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-QnnODucG-1583433950254)(https://raw.githubusercontent.com/Coxhuang/yosoro/master/20200226165445-image.png)]

解決辦法:如果只有在修改事務完全提交之後纔可以讀取數據,則可以避免該問題。

#3.1.4 幻象讀

一個事務中,讀取到了其他事務新增的數據,彷彿出現了幻象。(幻讀與不可重複讀類似,不可重複讀是讀到了其他事務update/delete的結果,幻讀是讀到了其他事務insert的結果)。例如:目前工資爲1000的員工有10人。那麼事務1中讀取所有工資爲1000的員工,得到了10條記錄;這時事務2向員工表插入了一條員工記錄,工資也爲1000;那麼事務1再次讀取所有工資爲1000的員工共讀取到了11條記錄。

20200226165834-image.png

解決辦法:如果在操作事務完成數據處理之前,任何其他事務都不可以添加新數據,則可避免該問題

#3.2 MySQL隔離級別?

數據庫事務的隔離級別有4個,由低到高依次爲:

  • Read uncommitted(未授權讀取、讀未提交)
  • Read committed(授權讀取、讀提交)
  • Repeatable read(可重複讀取)
  • Serializable(序列化)

這四個級別可以逐個解決髒讀、不可重複讀、幻象讀這幾類問題。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-TItO3Trj-1583433950263)(https://raw.githubusercontent.com/Coxhuang/yosoro/master/20200303165736-image.png)]

#3.2.1 Read uncommitted(未授權讀取、讀未提交)

就是一個事務可以讀取另一個未提交事務的數據。最低級別,它存在4個常見問題(髒讀、不可重複讀、幻讀、丟失更新)。

#3.2.2 Read committed(授權讀取、讀提交)

就是一個事務要等另一個事務提交後才能讀取數據。 它解決了髒讀問題,存在3個常見問題(不可重複讀、幻讀、丟失更新)。

#3.2.3 Repeatable read(可重複讀取)

MySQL默認隔離級別,在一個事務中,直到事務結束前,都可以反覆讀取到事務剛開始時看到的數據,並一直不會發生變化,避免了髒讀、不可重複讀現象,但是它還是無法解決幻讀問題。 。它解決了髒讀和不可重複讀,還存在2個常見問題(幻讀、丟失更新)。

#3.2.4 Serializable(序列化)

序列化,或串行化。就是將每個事務按一定的順序去執行,它將隔離問題全部解決,但是這種事務隔離級別效率低下,比較耗數據庫性能,一般不使用。

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