理解隔離性
MySQL服務(wù)可能會同時(shí)被多個客戶端進(jìn)程(線程)訪問,訪問的方式以事務(wù)方式進(jìn)行
一個事務(wù)可能由多條SQL構(gòu)成,也就意味著,任何一個事務(wù),都有執(zhí)行前,執(zhí)行中,執(zhí)行后的階段。而所謂的原子性,其實(shí)就是讓用戶層,要么看到執(zhí)行前,要么看到執(zhí)行后。執(zhí)行中出現(xiàn)問題,可以隨時(shí)回滾。所以單個事務(wù),對用戶表現(xiàn)出來的特性,就是原子性
所有的事務(wù)都有執(zhí)行過程,那么在多個事務(wù)各自執(zhí)行多個SQL的時(shí)候,就還是有可能會出現(xiàn)互相影響的情況。比如:多個事務(wù)同時(shí)訪問同一張表,甚至同一行數(shù)據(jù)。 舉個例子,如你媽媽給你說:要么別學(xué),要學(xué)就學(xué)到最好。至于你怎么學(xué),中間有什么困難,你媽媽不關(guān)心。那么你的學(xué)習(xí),對你媽媽來講,就是原子的。那么你學(xué)習(xí)過程中,很容易受別人干擾,此時(shí),就需要將你的學(xué)習(xí)隔離開,保證你的學(xué)習(xí)環(huán)境是健康的。
數(shù)據(jù)庫中,為了保證事務(wù)執(zhí)行過程中盡量不受干擾,就有了一個重要特征:隔離性 ;允許事務(wù)受不同程度的干擾,就有了一種重要特征:隔離級別
在事務(wù)場景中,隔離是必要的。是運(yùn)行中的事務(wù)進(jìn)行互相隔離。在事務(wù)運(yùn)行中,“不會”出現(xiàn)互相干擾,這就是隔離性;根據(jù)影響程度的不同,隔離級別。
隔離級別
讀未提交Read Uncommitted
:在該隔離級別,所有的事務(wù)都可以看到其他事務(wù)沒有提交的執(zhí)行結(jié)果。(實(shí)際中不可能使用這種隔離級別),但是相當(dāng)于沒有任何隔離性,也會有很多并發(fā)問題,如臟讀,幻讀,不可重復(fù)度等,我們前面一開始所用的就是這個隔離性,方便演示。
讀提交Read Committed
:該隔離級別是大多數(shù)數(shù)據(jù)庫的默認(rèn)的隔離級別(不是MySQL默認(rèn)的)。它滿足了隔離的簡單定義:一個事務(wù)只能看到其他的已經(jīng)提交的事務(wù)所做的改變。這種隔離級別會引起不可重復(fù)讀,即一個事務(wù)執(zhí)行時(shí),如果多次select,可能得到不同的結(jié)果
可重復(fù)度Repeatable Read
:這是MySQL默認(rèn)的隔離級別,它確保同一個事務(wù),在執(zhí)行中,多次讀取操作數(shù)據(jù)時(shí),會看到同樣的數(shù)據(jù)行。但是會有幻讀問題。
串行化
:這是事務(wù)的最高隔離級別,它通過強(qiáng)制事務(wù)排序,使之不可能相互沖突,從而解決了幻讀的問題。它在每個讀的數(shù)據(jù)上面加上了共享鎖,但是可能會導(dǎo)致超時(shí)和鎖競爭(這種隔離級別太極端,實(shí)際生產(chǎn)中基本不使用)
查看與設(shè)置隔離性
- 查看
-- 查看全局隔離級別
select @@global.tx_isolation;
-- 查看會話全局隔離級別
select @@session.tx_ioslation;
-- 默認(rèn)
select @@tx_isolation;
- 設(shè)置
設(shè)置session級別:
-- 設(shè)置當(dāng)前會話 or 全局隔離級別語法
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
設(shè)置會話級別只會影響session以及默認(rèn)的會話級別。
設(shè)置全局級別:
如果退出重新登錄mysql,session也會改變:
隔離級別一般保持一致。
讀未提交Read Uncommitted
設(shè)置讀未提交:
set global transaction isolation level read uncommitted;
設(shè)置完畢后記得退出mysql重新登錄。才會生效
一端啟動事務(wù)同時(shí)插入和更新數(shù)據(jù)。但是沒有提交事務(wù):
但是另一端也啟動事務(wù),也能看到插入和更新后的數(shù)據(jù):讀到了沒有提交的數(shù)據(jù),這就是讀未提交:
讀未提交:一個事務(wù)正在運(yùn)行,另一個事務(wù)也啟動起來,對數(shù)據(jù)做增刪改操作,如果隔離級別是讀未提交,增刪改會被立馬看到,這就是讀未提交,沒有提交就會被看到。
所以讀未提交幾乎是沒有加鎖,雖然效率高,但是問題太多,不建議采用。
一個事務(wù)在執(zhí)行中,讀到另一個執(zhí)行中事務(wù)的更新(或其他操作)但是未commit的數(shù)據(jù),這種現(xiàn)象叫做臟讀
臟讀現(xiàn)象是一個特別不合理的現(xiàn)象,一直能查到別人沒有提交的數(shù)據(jù)。
讀提交Read Committed
設(shè)置讀提交的隔離級別
set global transaction isolation level read committed;
一端啟動事務(wù)進(jìn)行插入和更新數(shù)據(jù):
另一端查看表的數(shù)據(jù):沒有發(fā)生變化
當(dāng)一端的事務(wù)提交之后:
另一端事務(wù)在沒有結(jié)束的情況下(commit之后也能看到),也能看到變化了:
并發(fā)執(zhí)行事務(wù),一個事務(wù)對數(shù)據(jù)做了修改,操作期間另一個看不到,而一旦提交了,就能看到了。這就是讀提交的隔離級別。
多個事務(wù)并發(fā)執(zhí)行時(shí),此時(shí)還在當(dāng)前事務(wù)中
,并未commit,那么就造成了,同一個事務(wù)內(nèi),同樣的讀取,在不同的時(shí)間段(依舊還在事務(wù)操作中)讀取到了不同的值,這種現(xiàn)象叫做不可重復(fù)讀
(non reapeatable read),比如我們上面的圖片就是,在一個事務(wù)運(yùn)行的內(nèi)部還未commit,但是同樣的讀取卻讀取到了不同的值。
讀提交出現(xiàn)的不可重復(fù)讀是有問題的:比如在一個事務(wù)中,按照薪資等級分成不同的等級,然后分發(fā)年終獎品,我們查找tom這個名字,此時(shí)已經(jīng)找到了,但是此時(shí)另一個事務(wù)對tom這個名字的薪資進(jìn)行了修改,而剛開始的事務(wù)還沒有提交,同一個事務(wù)中,同樣的讀取,此時(shí)tom這個人就需要分發(fā)兩個獎品,這是不合理的,一個人只能按照薪資等級分發(fā)到一個獎品。所以我們不想讓一個事務(wù)運(yùn)行中讀到另一個事務(wù)的提交。
可重復(fù)讀 Repeatable Read
解決兩個并發(fā)的事務(wù),一方提交,一方增刪改,提交也不會影響到另一方。
設(shè)置事務(wù)隔離級別:
set global transaction isolation level repeatable read;
此時(shí)的事務(wù)隔離級別是可重復(fù)度的。
現(xiàn)在其中一個事務(wù)中對數(shù)據(jù)進(jìn)行增刪改,同時(shí)提交:
另一個事務(wù)啟動后沒有提交查看表的數(shù)據(jù):
可以看到,在拎一個終端中,事務(wù)無論什么時(shí)候進(jìn)行查找,看到的結(jié)果都是一致的,這叫做可重復(fù)讀!
當(dāng)事務(wù)結(jié)束掉自然就能看到變化了:
多次查看,發(fā)現(xiàn)終端A在對應(yīng)事務(wù)中insert的數(shù)據(jù),在終端B的事務(wù)周期中,也沒有什么影響,也符合可重復(fù)的特點(diǎn)。
但是,一般的數(shù)據(jù)庫在可重復(fù)讀情況的時(shí)候,無法屏蔽其他事務(wù)insert的數(shù)據(jù) ,因?yàn)楦綦x性是對數(shù)據(jù)做加鎖完成的,而insert待插入的數(shù)據(jù)因?yàn)椴⒉淮嬖?,那么一般加鎖無法屏蔽這類問題,會造成雖然大部分內(nèi)容是可重復(fù)讀的,但是insert的數(shù)據(jù)在可重復(fù)讀情況被讀取出來,導(dǎo)致多次查找時(shí),會多查找出來新的記錄,就如同產(chǎn)生了幻覺。這種現(xiàn)象,叫做幻讀
.很明顯,MySQL在RR級別的時(shí)候,是解決了幻讀問題的。
串行化serializable
對所有操作全部加鎖,事務(wù)進(jìn)行串行化,不是sql,不會有問題,但是只要串行化,效率很低,幾乎完全不會被采用
設(shè)置隔離級別串行化:
set global transaction isolation level serializable;
select * from account; -- 兩個讀取不會串行化,共享鎖
查找時(shí)沒有阻塞:
總結(jié):
其中隔離級別越嚴(yán)格,安全性越高,但數(shù)據(jù)庫的并發(fā)性能也就越低,往往需要在兩者之間找一個平衡點(diǎn)。
不可重復(fù)讀的重點(diǎn)是修改和刪除:同樣的條件, 你讀取過的數(shù)據(jù),再次讀取出來發(fā)現(xiàn)值不一樣了
幻讀的重點(diǎn)在于新增:同樣的條件, 第1次和第2次讀出來的記錄數(shù)不一樣
說明: mysql 默認(rèn)的隔離級別是可重復(fù)讀,一般情況下不要修改
上面的例子可以看出,事務(wù)也有長短事務(wù)這樣的概念。事務(wù)間互相影響,指的是事務(wù)在并行執(zhí)行的時(shí)候,即都沒有commit的時(shí)候,影響會比較大
一致性(Consistency)
事務(wù)執(zhí)行的結(jié)果,必須使數(shù)據(jù)庫從一個一致性狀態(tài),變到另一個一致性狀態(tài)。當(dāng)數(shù)據(jù)庫只包含事務(wù)成功提交的結(jié)果時(shí),數(shù)據(jù)庫處于一致性狀態(tài)。如果系統(tǒng)運(yùn)行發(fā)生中斷,某個事務(wù)尚未完成而被迫中斷,而改未完成的事務(wù)對數(shù)據(jù)庫所做的修改已被寫入數(shù)據(jù)庫,此時(shí)數(shù)據(jù)庫就處于一種不正確(不一致)的狀態(tài)。因此一致性是通過原子性來保證的。
其實(shí)一致性和用戶的業(yè)務(wù)邏輯強(qiáng)相關(guān),一般MySQL提供技術(shù)支持,但是一致性還是要用戶業(yè)務(wù)邏輯做支撐,也就是,一致性,是由用戶決定的文章來源:http://www.zghlxwxcb.cn/news/detail-497704.html
而技術(shù)上,通過AID保證C文章來源地址http://www.zghlxwxcb.cn/news/detail-497704.html
到了這里,關(guān)于【MySql】MySql事務(wù)隔離級別與一致性的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!