MySQL事務(wù)及Spring隔離級(jí)別實(shí)現(xiàn)原理詳解
1、事務(wù)具有ACID特性
- 原子性(atomicity):一個(gè)事務(wù)被事務(wù)不可分割的最小工作單元,要么全部提交,要么全部失敗回滾。
- 一致性(consistency):數(shù)據(jù)庫總是從一致性狀態(tài)到另一個(gè)一致性狀態(tài),它只包含成功事務(wù)提交的結(jié)果
- 隔離型(isolation):事務(wù)所做的修改在最終提交一起,對其他事務(wù)是不可見的
- 持久性(durability):一旦事務(wù)提交,則其所做的修改就會(huì)永久保存到數(shù)據(jù)庫中。
2、事務(wù)的隔離級(jí)別
1)隔離級(jí)別的定義與問題
- READ UNCOMMITTED(讀未提交):事務(wù)的修改,即使沒有提交,對其他事務(wù)也都是可見的。事務(wù)能夠讀取未提交的數(shù)據(jù),這種情況稱為臟讀。
- READ COMMITTED(讀已提交):事務(wù)讀取已提交的數(shù)據(jù),大多數(shù)數(shù)據(jù)庫的默認(rèn)隔離級(jí)別。當(dāng)一個(gè)事務(wù)在執(zhí)行過程中,數(shù)據(jù)被另外一個(gè)事務(wù)修改,造成本次事務(wù)前后讀取的信息不一樣,這種情況稱為不可重復(fù)讀。
- PEPEATABLE READ(可重復(fù)讀):這個(gè)級(jí)別是MySQL的默認(rèn)隔離級(jí)別,它解決了臟讀的問題,同時(shí)也保證了同一個(gè)事務(wù)多次讀取同樣的記錄是一致的,但這個(gè)級(jí)別還是會(huì)出現(xiàn)幻讀的情況。幻讀是指當(dāng)一個(gè)事務(wù)A讀取某一個(gè)范圍的數(shù)據(jù)時(shí),另一個(gè)事務(wù)B在這個(gè)范圍插入行,A事務(wù)再次讀取這個(gè)范圍的數(shù)據(jù)時(shí),會(huì)產(chǎn)生幻行。特別說明:InnoDB和XtraDB存儲(chǔ)引擎通過多版本并發(fā)控制(MVCC,Multiversion Concurrency Control)解決了幻讀問題,它使用間隙鎖(next-key locking)鎖定查詢涉及的行和索引中的間隙,防止幻影行的插入。
- SERIALIZABLE(可串行化):這個(gè)事務(wù)是最高的隔離級(jí)別,它強(qiáng)制事務(wù)串行執(zhí)行,避免了幻讀問題。簡單來說,SERIALIZABLE會(huì)在讀取的每一行數(shù)據(jù)上都加鎖,所以可能會(huì)導(dǎo)致大量的超時(shí)和鎖競爭
隔離級(jí)別 | 臟讀可能性 | 不可重復(fù)度可能性 | 幻讀可能性 | 加鎖讀 |
READ UNCONMITED | Yes | Yes | Yes | No |
RED COMMITED | No | Yes | Yes | No |
REPEATABLE READ | No | No | Yes | No |
SERIALIZABLE | No | No | No | Yes |
2)如果查看修改和MySQL的隔離級(jí)別
show variables like 'tx_isolation'; # 查看隔離級(jí)別,MySQL8以前 show variables like 'transaction_isolation'; # 查看隔離級(jí)別,MySQL8 set global transaction_isolation='READ-COMMITTED'; // 設(shè)置隔離級(jí)別,閥域READ-UNCOMMITTED、READ-COMMITTED、REPEATABLE-READ、SERIALIZABLE
事務(wù)的隔離級(jí)別可以是Session層的,我們可以對不同的Session設(shè)置不同級(jí)別:
set session transaction isolation level read uncommitted; set session transaction isolation level read committed; set session transaction isolation level repeatable read; set session transaction isolation level serializable;
3)Spring事務(wù)隔離級(jí)別
Spring事務(wù)默認(rèn)使用數(shù)據(jù)庫的隔離級(jí)別,可以通過注解@Transactional中的isolation參數(shù)調(diào)整Session級(jí)的隔離級(jí)別。隔離級(jí)別是會(huì)話級(jí)別的,JDBC的java.sql.Connection接口支持隔離級(jí)別的設(shè)置。
Spring在開啟事務(wù)時(shí)(DataSourceTransactionManager.doBegin),根據(jù)注解配置,對Connection的隔離級(jí)別進(jìn)行設(shè)置:
MySQL驅(qū)動(dòng)com.mysql.cj.jdbc.ConnectionImpl執(zhí)行SQL語句調(diào)整會(huì)話級(jí)的隔離級(jí)別
3、死鎖
死鎖是指兩個(gè)或多個(gè)事務(wù)在同一資源上相互占用,并請求鎖定對方占用的資源,從而導(dǎo)致惡性循環(huán)。死鎖示例:
# 事務(wù)一 start transaction; update account set money=10 where id=1; update account set money=20 where id=2; commit; # 事務(wù)二 start transaction; update account set money=10 where id=2; update account set money=20 where id=1; commit;
假設(shè)碰巧,事務(wù)一和事務(wù)二同時(shí)執(zhí)行完第一個(gè)update語句,接著準(zhǔn)備執(zhí)行第二條update語句,卻發(fā)現(xiàn)記錄已被對方鎖定,然后2個(gè)事務(wù)都等待對方釋放資源,同時(shí)持有對方需要的鎖,這樣就會(huì)出現(xiàn)死循環(huán)。
為了避免死鎖問題,數(shù)據(jù)庫實(shí)現(xiàn)了各種死鎖檢測和死鎖超長機(jī)制,InnoDB處理死鎖的方式是:將持有最少行級(jí)排他鎖的事務(wù)進(jìn)行回滾。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
MySQL主從復(fù)制搭建流程分步實(shí)現(xiàn)
這篇文章主要介紹了MySQL的主從復(fù)制原理詳細(xì)分析,讀寫分離是基于主從復(fù)制來實(shí)現(xiàn)的。文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-11-11Windows安裝MySQL8.0.28.0.msi方式(圖文詳解)
這篇文章主要介紹了Windows安裝MySQL8.0.28.0.msi,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03