MyISAM 不支持事務, innoDB支持事務安全
多個事務可能存在問題
在多個事務共同操做時容易出現這樣幾個問題:post
- 髒讀(dirty read)
- 不可重複讀(nonrepeatable)
- 幻讀(phantom read)
來具體看一下這三個問題會有什麼影響性能
髒讀:A事務讀取到並使用了B事務還未提交的數據,這時若是B事務被撤回,則A操做的數據則是不許確的。好比如下銀行存取款例子:學習
A事務 |
B事務 |
|
開啓事務 |
開啓事務 |
|
|
查詢餘額爲1000 |
|
取出500,餘額變爲500 |
查詢餘額爲500(髒數據) |
|
|
撤銷事務,此時餘額爲1000 |
存入100,此時餘額爲600 |
|
提交事務 |
|
不可重複讀: A事務讀取了B事務已經提交的數據。同一個事務內查詢到不一樣的結果,好比A查詢到銀行帳戶有200元,而後準備取錢,這時B用同一個帳號將錢轉走,A取錢時會提示餘額不足,A在同一個事務內發現餘額發生了變化,第一次查到的結果不可重複
幻讀:解決了不可重複讀以後,保證同一個事務裏,查詢的結果都是事務開始時的狀態(一致性)。可是,若是另外一個事務同時插入了新的數據,則本事務再次更新時,就會發現這些新插入的數據,好像以前讀到的不完整的數據是鬼影同樣幻覺線程
隔離級別
爲了解決髒讀、不可重複讀、幻讀,有了"隔離級別這個概念"
SQL隔離級別包括:事務
- 讀未提交(read uncommitted):別人修改數據的事務尚未提交,我在個人事務內也能讀到
- 讀可提交(read committed):別人修改數據的事務提交後,我在個人事務內才能讀到
- 可重複讀(repeatable read):別人修改數據的事務提交後我也讀不到,我只能讀到我事務開始時保持的數據狀態,個人事務內數據不受到其餘事務的影響
- 串行化(serializable):個人事務還沒提交時,比我晚開始的事務只能是等待狀態,同時只能有一個事務在進行
好比個人帳戶有500元,按照時間順序執行如下兩個事務get
A事務 |
B事務 |
啓動事務A查詢餘額爲500 |
|
|
啓動事務B查詢到餘額500 |
|
存入100元 |
再次查詢餘額Q1 |
|
|
提交事務B |
查詢餘額Q2 |
|
提交事務A |
|
再次查詢餘額Q3 |
|
根據不一樣的隔離級別,Q一、Q二、Q3會有不一樣的值。下面來詳細分析:it
- 讀未提交(read uncommitted):可以讀到其餘事務未提交的數據,也就是B事務存入100雖然沒有提交,可是事務A第二次查詢餘額已經發生變化,Q1爲600,後面沒有涉及到金額的變化,因此Q2/Q3的值也是600
- 讀可提交(read committed):可以讀到其餘事務已經提交的數據,查詢Q1時,由於B事務尚未提交,因此並無影響到A事務,因此Q1的值仍是500,當查詢Q2時,B事務已經提交,A事務能夠讀到,因此Q二、Q3都是600
- 可重複讀(repeatable read):一個事務內的數據不受其餘事務的影響,所以在A事務提交前,因此查到的餘額不變,同事務開始時的值是同樣的,所以Q一、Q2都爲500。A事務提交後,能夠發現B事務形成的數據影響,因此Q3的值爲600
- 串行化(serializable):事務A開始後,事務B再發起,則會被鎖住,當事務A提交後,事務B才能進入,因此事務A提交前Q一、Q2的值是不變的都是500,提交事務A後,事務B纔開始解鎖執行,B提交後,Q3查詢到的值爲600
由以上能夠看出這4種隔離級別,從上至下性能依次下降,安全性依次提升。io
事務的啓動方式
事務有兩種啓動方式:table
- 顯式啓動事務語句,begin或者start transaction,提交commit,回滾rollback
- set autocommit=0,該命令會把這個線程的自動提交關掉。這樣只要執行一個select語句,事務就啓動,並不會自動提交,直到主動執行commit或rollback或斷開鏈接。
本文爲極客時間《MySQL實戰45講》的學習筆記,其中含有部分原文,若有侵權行爲請聯繫我馬上刪除
第二節:MySQL系列之一條更新SQL的生命歷程