mysql隔離級別和鎖的關(guān)系(spring默認(rèn)事務(wù)隔離級別)
- 夕逆IT
- 前端設(shè)計(jì)
- 2023-08-13
- 252
大家好,mysql隔離級別和鎖的關(guān)系相信很多的網(wǎng)友都不是很明白,包括spring默認(rèn)事務(wù)隔離級別也是一樣,不過沒有關(guān)系,接下來就來為大家分享關(guān)于mysql隔離級別和鎖的...
大家好,mysql隔離級別和鎖的關(guān)系相信很多的網(wǎng)友都不是很明白,包括spring默認(rèn)事務(wù)隔離級別也是一樣,不過沒有關(guān)系,接下來就來為大家分享關(guān)于mysql隔離級別和鎖的關(guān)系和spring默認(rèn)事務(wù)隔離級別的一些知識點(diǎn),大家可以關(guān)注收藏,免得下次來找不到哦,下面我們開始吧!
數(shù)據(jù)庫哪個(gè)隔離級別可以實(shí)現(xiàn)臟讀
對于同時(shí)運(yùn)行的多個(gè)事務(wù),當(dāng)這些事務(wù)訪問數(shù)據(jù)庫中相同的數(shù)據(jù)時(shí),如果沒有采取必要的隔離機(jī)制,就會導(dǎo)致各種并發(fā)問題:?臟讀:對于兩個(gè)事物T1,T2,T1讀取了已經(jīng)被T2更新但還沒有被提交的字段.之后,若T2回滾,T1讀取的內(nèi)容就是臨時(shí)且無效的.?不可重復(fù)讀:對于兩個(gè)事物T1,T2,T1讀取了一個(gè)字段,然后T2更新了該字段.之后,T1再次讀取同一個(gè)字段,值就不同了.?幻讀:對于兩個(gè)事物T1,T2,T1從一個(gè)表中讀取了一個(gè)字段,然后T2在該表中插入了一些新的行.之后,如果T1再次讀取同一個(gè)表,就會多出幾行.數(shù)據(jù)庫事務(wù)的隔離性:數(shù)據(jù)庫系統(tǒng)必須具有隔離并發(fā)運(yùn)行各個(gè)事務(wù)的能力,使它們不會相互影響,避免各種并發(fā)問題.一個(gè)事務(wù)與其他事務(wù)隔離的程度稱為隔離級別.數(shù)據(jù)庫規(guī)定了多種事務(wù)隔離級別,不同隔離級別對應(yīng)不同的干擾程度,隔離級別越高,數(shù)據(jù)一致性就越好,但并發(fā)性越弱數(shù)據(jù)庫提供了4中隔離級別:隔離級別描述READUNCOMMITTED(讀未提交數(shù)據(jù))允許事務(wù)讀取未被其他事務(wù)提交的變更,臟讀、不可重復(fù)讀和幻讀的問題都會出現(xiàn)READCOMMITED(讀已提交數(shù)據(jù))只允許事務(wù)讀取已經(jīng)被其他事務(wù)提交的變更,可以避免臟讀,但不可重復(fù)讀和幻讀問題仍然會出現(xiàn)REPEATABLEREAD(可重復(fù)讀)確保事務(wù)可以多次從一個(gè)字段中讀取相同的值,在這個(gè)事務(wù)持續(xù)期間,禁止其他事務(wù)對這個(gè)字段進(jìn)行更新,可以避免臟讀和不可重復(fù)讀,但幻讀的問題依然存在SERIALIZABLE(串行化)確保事務(wù)可以從一個(gè)表中讀取相同的行,在這個(gè)事務(wù)持續(xù)期間,禁止其他事務(wù)對該表執(zhí)行插入、更新和刪除操作,所有并發(fā)問題都可以避免,但性能十分低Oracle支持的2種事務(wù)隔離級別:READCOMMITED,SERIALIZABLE.Oracle默認(rèn)的事務(wù)隔離級別為:READCOMMITEDMysql支持4中事務(wù)隔離級別.Mysql默認(rèn)的事務(wù)隔離級別為:REPEATABLEREAD
MySQL的可重復(fù)讀級別能解決幻讀嗎
現(xiàn)在的主流數(shù)據(jù)庫都使用MVCC,用了之后的RR隔離級別是不會出現(xiàn)幻讀的。
不同的資料講的RR是199X年的ANSISQL標(biāo)準(zhǔn),但現(xiàn)實(shí)的數(shù)據(jù)庫不一定符合標(biāo)準(zhǔn)(事實(shí)上,沒有幻讀是更好的事情)。
mysql隔離級別是哪本書上的
這個(gè)不是書上的,隔離級別有,讀已提交,不可重復(fù)讀,可重復(fù)讀,臟讀,幻讀
Java如何實(shí)現(xiàn)對Mysql數(shù)據(jù)庫的行鎖
在講鎖之前,首先講講兩個(gè)概念吧,嘿嘿行鎖和MySQL事務(wù)屬性
行鎖
mysql實(shí)現(xiàn)行級鎖的兩大前提就是,innodb引擎并且開啟事務(wù)。由于MySQL/InnoDB的加鎖分析,一般日常中使用方式為:select....fromtablewhere.....forupdate語句并且在RepeatableRead事務(wù)隔離級別下。
行鎖的劣勢:開銷大;加鎖慢;會出現(xiàn)死鎖
行鎖的優(yōu)勢:鎖的粒度小,發(fā)生鎖沖突的概率低;處理并發(fā)的能力強(qiáng)
加鎖的方式:自動(dòng)加鎖。對于UPDATE、DELETE和INSERT語句,InnoDB會自動(dòng)給涉及數(shù)據(jù)集加排他鎖;對于普通SELECT語句,InnoDB不會加任何鎖;當(dāng)然我們也可以顯示的加鎖:
共享鎖:select*fromtablewhere“條件”+lockinsharemore
排他鎖:select*fromtablewhere”條件“+forupdate
MySQL事務(wù)屬性
事務(wù)是由一組SQL語句組成的邏輯處理單元,事務(wù)具有ACID屬性。
原子性(Atomicity):事務(wù)是一個(gè)原子操作單元。在當(dāng)時(shí)原子是不可分割的最小元素,其對數(shù)據(jù)的修改,要么全部成功,要么全部都不成功。
一致性(Consistent):事務(wù)開始到結(jié)束的時(shí)間段內(nèi),數(shù)據(jù)都必須保持一致狀態(tài)。
隔離性(Isolation):數(shù)據(jù)庫系統(tǒng)提供一定的隔離機(jī)制,保證事務(wù)在不受外部并發(fā)操作影響的”獨(dú)立”環(huán)境執(zhí)行。
持久性(Durable):事務(wù)完成后,它對于數(shù)據(jù)的修改是永久性的,即使出現(xiàn)系統(tǒng)故障也能夠保持。
舉例說明
innodb引擎中行級鎖分為以下三種鎖
1.RecordLock
單個(gè)行記錄上的鎖
2.GapLock
間隙鎖,鎖定一個(gè)范圍,不包括記錄本身
3.Next-KeyLock
鎖定一個(gè)范圍和記錄本身
話不多說直接代碼開干
代碼:select*fromtablewhereorder_no='20200521xxx'forupdate;
order_no是主鍵的時(shí)候,可以確定唯一一條數(shù)據(jù),所以在此加上RecordLock(即為單個(gè)記錄上鎖)
order_no是普通索引的時(shí)候,innodb層面會根據(jù)條件鎖定一個(gè)范圍,在查詢的時(shí)候聚簇索引上加RecordLock(即為單個(gè)記錄上鎖)
order_no不是索引的時(shí)候,本條sql會進(jìn)行全表掃描,會在所有的聚簇索引上加鎖,相當(dāng)于全表鎖,這個(gè)是在mysqlinnodb引擎層面決定。
還有一種情況,假如后面跟多個(gè)情況
代碼:select*fromtablewhereorder_no='20200521'andcode='xxx'forupdate;
經(jīng)過上面分析
order_no主鍵,code不是索引,查詢都只有一條數(shù)據(jù),加RecordLock
order_no普通索引,code不是索引,會先掃描order_no='20200521',范圍下加鎖
結(jié)論:我們的forupdate并不時(shí)都鎖一條記錄,也并不是只有一個(gè)鎖,但是也包含我們常用的手段了,在項(xiàng)目中可以實(shí)踐用用哦
好了,如果對您有幫助,記得關(guān)注收藏轉(zhuǎn)發(fā)哦,我會一直在這里等候與您交流
Mysql高并發(fā),數(shù)據(jù)亂竄
你說的這個(gè),描述過于簡單,無法判斷具體情況。
不過,mysql默認(rèn)的隔離級別是Repeatableread。會出現(xiàn)幻讀。如果是Readcommited,會出現(xiàn)不可重復(fù)讀。
如下:
==============================================================
隔離級別--------------臟讀---不可重復(fù)讀---幻讀
==============================================================
未提交讀(Readuncommitted)可能可能可能
已提交讀(Readcommitted)不可能可能可能
可重復(fù)讀(Repeatableread)不可能不可能可能
可串行化(Serializable)不可能不可能不可能
==============================================================
什么是不可重復(fù)讀呢?
在一個(gè)事務(wù)中,第一次讀和第二次,有可能讀到的同一條數(shù)據(jù)不一致。
比如:
begin
selectnamefrombwherecol=5;
比如結(jié)果為:xiaoli
updatebsetinfo='abc'wherecol=5andname='xiaoli';
我們并沒有修改,col=5的name字段,但是再次讀這條數(shù)據(jù)的時(shí)候
selectnamefrombwherecol=5;
這里結(jié)果,可能是'zhangsan'。
commit
為什么這樣呢?當(dāng)你這個(gè)事務(wù)在執(zhí)行的過程中,其他事務(wù)提交了一個(gè)update,修改了col=5這條數(shù)據(jù)。
什么是幻讀呢?就是在一個(gè)事務(wù)中,已經(jīng)對符合條件的數(shù)據(jù)進(jìn)行了變更,但是提交前再次讀取的時(shí)候,還會有滿足要求的數(shù)據(jù),因?yàn)樵谀愕氖聞?wù)過程中,有其他的事務(wù)進(jìn)行了新數(shù)據(jù)的提交,導(dǎo)致你又出現(xiàn)了滿足條件的數(shù)據(jù)。
比如:
begin
selectcount(*)frombwherecol=5;
比如一共三條
updatebsetcol=10wherecol=5;
提示已經(jīng)更改了3行數(shù)據(jù)。
這時(shí)候已經(jīng)修改但是沒有提交,
selectcount(*)frombwherecol=5;
發(fā)現(xiàn),又出現(xiàn)了一條。
commit
就會發(fā)現(xiàn)怎么還有一條沒有更新到呢?
這就是幻讀。
如果你非要解決這個(gè)問題的話,setglobaltransactionisolationlevelserializable;
這種情況下,我在一個(gè)事務(wù)中執(zhí)行的時(shí)候,其他事務(wù)只能等待。哪怕我只執(zhí)行了一個(gè)select語句。
但是這種級別,基本上談不上高并發(fā),也高并發(fā)不起來。因此一般生產(chǎn)只能在高并發(fā)和事務(wù)上做一個(gè)平衡。
不知道你說的是不是這個(gè)問題,這種問題需要程序去配合當(dāng)前的事務(wù)級別。
mysql 的隔離是什么
mysql的隔離就是指,SQL標(biāo)準(zhǔn)定義了四種隔離級別,用來限定事務(wù)內(nèi)外的哪些改變是可見的,哪些是不可見的。
譬如,讀取未提交的數(shù)據(jù)【ReadUncommitted】在該隔離級別,所有的事務(wù)都可以看到其他事務(wù)沒有提交的執(zhí)行結(jié)果。
還有,讀取提交的內(nèi)容【ReadCommitted】該隔離級別是大多數(shù)數(shù)據(jù)庫的默認(rèn)的隔離級別(不是MySQL默認(rèn)的)。它滿足了隔離的簡單定義:一個(gè)事務(wù)只能看到其他的已經(jīng)提交的事務(wù)所做的改變。這種隔離級別也支持不可重復(fù)讀,即同一個(gè)select可能得到不同的結(jié)果。等等
好了,關(guān)于mysql隔離級別和鎖的關(guān)系和spring默認(rèn)事務(wù)隔離級別的問題到這里結(jié)束啦,希望可以解決您的問題哈!
本文鏈接:http://xinin56.com/qianduan/1753.html