数据库系列:RR和RC下,快照读的区别
數(shù)據(jù)庫(kù)系列:MySQL慢查詢分析和性能優(yōu)化
數(shù)據(jù)庫(kù)系列:MySQL索引優(yōu)化總結(jié)(綜合版)
數(shù)據(jù)庫(kù)系列:高并發(fā)下的數(shù)據(jù)字段變更
數(shù)據(jù)庫(kù)系列:覆蓋索引和規(guī)避回表
數(shù)據(jù)庫(kù)系列:數(shù)據(jù)庫(kù)高可用及無(wú)損擴(kuò)容
數(shù)據(jù)庫(kù)系列:使用高區(qū)分度索引列提升性能
數(shù)據(jù)庫(kù)系列:前綴索引和索引長(zhǎng)度的取舍
數(shù)據(jù)庫(kù)系列:MySQL引擎MyISAM和InnoDB的比較
數(shù)據(jù)庫(kù)系列:InnoDB下實(shí)現(xiàn)高并發(fā)控制
數(shù)據(jù)庫(kù)系列:事務(wù)的4種隔離級(jí)別
1 介紹
上一篇,我們介紹了 SQL92標(biāo)準(zhǔn)中事務(wù)的四種隔離級(jí)別,并討論了每種隔離級(jí)別下 臟讀、不可重復(fù)讀、幻讀 問(wèn)題是否可以解決:
| 隔離級(jí)別 | 臟讀 | 不可重復(fù)讀 | 幻讀 |
|---|---|---|---|
| 讀未提交:Read Uncommitted | ? | ? | × |
| 讀已提交:Read Committed | × | ? | × |
| 可重復(fù)讀:Repeatable Read | × | × | ? |
| 串行化:Serializable | × | × | × |
在 讀已提交(Read Committed) 和 可重復(fù)讀(Repeatable Read)兩種隔離級(jí)別上,數(shù)據(jù)庫(kù)底層采用了快照讀(Snapshot Read)的模式來(lái)實(shí)現(xiàn)高并發(fā)機(jī)制。
那RC 和 RR這兩種的隔離級(jí)別上的快照讀(Snapshot Read)有什么區(qū)別呢,咱們往下探索?
2 RC 和 RR下快照讀的區(qū)別
2.1 啥是快照讀?
MySQL中InnoDB存儲(chǔ)引擎的快照讀(Snapshot Read)是一種讀取數(shù)據(jù)的方式,它可以在事務(wù)開(kāi)始時(shí)創(chuàng)建一個(gè)數(shù)據(jù)快照,這個(gè)快照是一致性的,即讀取在事務(wù)開(kāi)始時(shí)或特定時(shí)間點(diǎn)之前提交的數(shù)據(jù)。底層原理是MySQL使用多版本并發(fā)控制(MVCC)機(jī)制來(lái)實(shí)現(xiàn)快照讀。在MVCC中,每個(gè)事務(wù)讀取的數(shù)據(jù)都是根據(jù)事務(wù)開(kāi)始時(shí)間點(diǎn)或快照時(shí)間點(diǎn)確定的。MySQL通過(guò)為每一行數(shù)據(jù)添加版本信息(如創(chuàng)建版本、刪除版本等),來(lái)保留歷史數(shù)據(jù)的多個(gè)版本。通過(guò)一種不加鎖一致性讀(Consistent Nonlocking Read)的方式來(lái)實(shí)現(xiàn)高并發(fā)的能力。
2.2 RU和Serializable為啥不采用快照讀?
- Serializable是串行化執(zhí)行,每個(gè)步驟都是順序的,一項(xiàng)事務(wù)執(zhí)行完成才能執(zhí)行另一項(xiàng)事務(wù),所以沒(méi)有MVCC 多版本的必要。
- RU是讀未提交,所有未完成的、未最終提交事務(wù)都可以被讀取到,所以任何有變化的數(shù)據(jù)都會(huì)被讀取到,即使是還沒(méi)有Commit,也沒(méi)有多版本的必要了。
2.3 讀已提交(Read Committed)
- 事務(wù)隔離級(jí)別的一種,簡(jiǎn)稱RC
- 解決了“臟讀”問(wèn)題,保證讀取到的所有都是已提交事務(wù)的,并最終落庫(kù)的
- 可能存在“讀幻影行”問(wèn)題,同一個(gè)事務(wù)中,前后連續(xù)的select可能讀到不同的結(jié)果集
2.4 可重復(fù)讀(Repeated Read)
- 事務(wù)隔離級(jí)別的一種,簡(jiǎn)稱RR
- 它不僅解決“臟讀”問(wèn)題,還解決了“讀幻影行”的問(wèn)題,同一個(gè)事務(wù)里,前后連續(xù)的select讀到始終相同的結(jié)果集
2.5 不同隔離級(jí)別下快照讀的區(qū)別
2.5.1 案例解析1
事務(wù)執(zhí)行順序如下:
| 時(shí)間序列 | A事務(wù) | B事務(wù) |
|---|---|---|
| T1 | 開(kāi)始事務(wù) | |
| T2 | 開(kāi)始事務(wù) | |
| T3 | 查詢xx賬戶余額(假設(shè)默認(rèn)有500元)★SELECT balance FROM acount WHERE customer_id=123456;
|
|
| T4 | xx賬戶存入1000元(未提交)★UPDATE acount SET balance=balance+1000.00 WHERE customer_id=123456;
|
|
| T5 | 查詢A賬戶余額 | |
| T6 | 提交事務(wù)★commit;
|
|
| T7 | 查詢A賬戶余額 |
-
Repeated Read 隔離級(jí)別
- T3讀到的結(jié)果肯定是500,這是B事務(wù)的第一個(gè)read
- T5讀到的結(jié)果也是500,因?yàn)锳事務(wù)還沒(méi)有提交
- T7讀到的結(jié)果還是500,因?yàn)锳事務(wù)是在時(shí)間T5之后提交的,T7讀到和T5一樣的結(jié)果(重復(fù)讀)
-
Read Committed 隔離級(jí)別
- T3讀到的結(jié)果肯定是500,這是B事務(wù)的第一個(gè)read
- T5讀到的結(jié)果也是500,因?yàn)锳事務(wù)還沒(méi)有提交
- T7讀到的結(jié)果還是1500,因?yàn)锳事務(wù)已經(jīng)提交,T7讀到Commit后的結(jié)果(讀已提交)
2.5.2 案例解析2
事務(wù)執(zhí)行順序如下:
| 時(shí)間序列 | A事務(wù) | B事務(wù) |
|---|---|---|
| T1 | 開(kāi)始事務(wù)(假設(shè)默認(rèn)有500元) | |
| T2 | 開(kāi)始事務(wù) | |
| T3 | xx賬戶存入1000元(未提交)★UPDATE acount SET balance=balance+1000.00 WHERE customer_id=123456;
|
|
| T4 | 提交事務(wù)★commit;
|
|
| T5 | 查詢A賬戶余額★SELECT balance FROM acount WHERE customer_id=123456;
|
- Repeated Read 隔離級(jí)別:唯一的一次讀是在A事務(wù)提交之后的讀,所以結(jié)果肯定是1500
- Read Committed 隔離級(jí)別:讀取已提交之后的數(shù)據(jù),所以毫無(wú)疑問(wèn)依然是1500
2.6 區(qū)別總結(jié)
首先,事務(wù)總能夠讀取到自己寫(xiě)入(update /insert /delete)的行記錄。而其他事務(wù)的提交,則分情況。
RC模式,快照讀總是能讀到最新的行數(shù)據(jù)快照,當(dāng)然,必須是已提交事務(wù)寫(xiě)入的。
RR模式,某個(gè)事務(wù)首次read記錄的時(shí)間為T(mén)1,之后的操作不會(huì)讀取到T1時(shí)間之后已提交事務(wù)寫(xiě)入的記錄,以保證連續(xù)相同的read讀到相同的結(jié)果集。
簡(jiǎn)單點(diǎn)說(shuō):
- RR下,事務(wù)在第一個(gè)Read操作時(shí),會(huì)建立Read View,并貫穿整個(gè)事務(wù)的過(guò)程,保證了可重復(fù)讀的效果。
- RC下,事務(wù)在每次Read操作時(shí),都會(huì)建立Read View,以保證獲取到的都是數(shù)據(jù)庫(kù)中最新的被Commit的值。
總結(jié)
以上是生活随笔為你收集整理的数据库系列:RR和RC下,快照读的区别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。