一.概念
事務就是一組原子性的sql查詢,或者說一個獨立的工作單元.
1.1 原子性
在事務執行的過程中要麼全執行,要麼全部執行失敗
示例:小明的總餘額爲1000,小明從銀行轉賬200元錢給小明的兒子,整個行爲可以視爲一個事務;
如下概要三個步驟:
1.判斷賬戶餘額是否大於200
2.從當前餘額扣減200
3.在小明兒子的賬戶增加餘額200
如上可視爲一個事務,要麼成功,要麼失敗.如第三步失敗,則回滾所有操作.
1.2 一致性
數據庫總是從一個一致性的狀態轉換到另外一個一致性的狀態
如上的例子中還是在第三步發生異常,那麼小明的總餘額也不會發生改變,事務回滾,保證數據一致性.
1.3 隔離性
事務所做的修改在最終提交之前,對於其他事務來說是不可見的
示例:
小明在進行轉賬操作,小明的老婆在另外一個地方也同樣進行的存錢的操作.取錢和存錢的兩個事務
之間是互相隔離的.在小明的事務提交之前,小明的老婆是不會發現餘額發生扣減.
1.4 持久性
事務的操作是能夠被持久化到硬盤,不會隨着系統宕機出現數據丟失
小明的賬戶發生扣減800,這個數據是持久化到硬盤的.即便停電宕機的操作,下次再次進來也是800,
這就是持久性.事務提交之後對系統的影響是持久,永久的.
從上面的例子,簡單的瞭解到了事務的一些基本概念.下面主要討論事務的隔離性.
二.事務隔離
在瞭解事務隔離性之前需要知道一些不同情況下出現的問題,由此我們在瞭解問題背景之後再去對應到
具體的隔離級別體會更加深刻.這裏討論的前提:事務併發操作
- 髒讀:讀取到了未提交的數據
示例:小明在查詢自己的餘額的過程中,小明的老婆在進行存錢的事務操作,操作的最後一步事務還沒有提交.
小明發現餘額發生了變化.讀取到了老婆在存錢而未提交的事務數據.這就是髒讀.
對應隔離級別:讀未提交[ReadUnCommited].
應用場景:較少.
- 不可重複讀:讀取了已提交的數據.
示例:事務a在讀取兩次讀取過程中,事務b在讀取間隙發生了該行數據的變更.
但未提交.在事務a讀取第二次之前,事務b進行提交.這時候事務a出現了兩次查詢不一樣的結果.
對應隔離級別:讀已提交[ReadCommited]
應用場景:大多數數據庫默認隔離級別.
- 可重複讀:在一個事務裏保證可以重複讀取.
對應隔離級別:可重複讀[ReadRepeat]
應用場景:mysql MVCC實現
- 幻讀:事務在讀取符合某個條件的結果集時.另外一個事務插入了符合這個條件的數據.這時候事務a
再次讀取發生了結果集增加的場景.
對應隔離級別:ReadSerializable應用場景:極少.
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-tZJAuyqZ-1591524396083)(https://user-gold-cdn.xitu.io/2020/6/7/1728e3b88df49293?w=1660&h=326&f=jpeg&s=94018)]
三. mysql 的MVCC[Multi-Version Concurrency Control]
數據庫引擎:InnoDB
數據庫隔離級別:RR
原理:樂觀鎖實現.
數據庫行數據的增加隱藏的兩列:系統版本,刪除版本.系統版本用以保存事務執行的版本,刪除版本用以保存
刪除時的事務版本.
1.插入
插入一條id爲1的記錄.createV爲1.
id | age | createV | delV |
---|---|---|---|
1 | 18 | 1 |
2.修改
修改id爲1的記錄中年齡爲15.則id爲1的最新createV爲事務版本號2.原有記錄的delV爲2
id | age | createV | delV |
---|---|---|---|
1 | 18 | 1 | 2 |
1 | 15 | 2 |
3.查詢
執行語句類似如下:查詢createV小於等於當前事務版本3.delV
select id,age from user where id=1[and createV<=3 and (delV>3 or devV is null)]
i:其中 createV<=3 能夠保證當前查詢的數據是當前查詢事務的開始之前的,要麼是本身開啓的事務所執行後
的結果
ii:delV>3 or devV is null .刪除版本大於當前事務版本或者沒有.保證當前查詢的數據沒有被刪除
id | age | createV | delV |
---|---|---|---|
1 | 18 | 1 | 2 |
1 | 15 | 2 |
4.刪除
將當前事務版本號作爲delV字段的刪除版本數據.這樣我們再來驗證下查詢邏輯有沒有問題.
select id,age from user where id=1[and createV<=5 and (delV>5 or devV is null)]
不可以被查到,沒問題
id | age | createV | delV |
---|---|---|---|
1 | 18 | 1 | |
1 | 15 | 2 | 2 |
1 | 15 | 2 | 4 |