解讀mysql的for update用法
mysql的for update用法
for update是在數(shù)據(jù)庫(kù)中上鎖用的,可以為數(shù)據(jù)庫(kù)中的行上一個(gè)排它鎖。
當(dāng)一個(gè)事務(wù)的操作未完成時(shí)候,其他事務(wù)可以讀取但是不能寫入或更新。
for update的使用場(chǎng)景
如果遇到存在高并發(fā)并且對(duì)于數(shù)據(jù)的準(zhǔn)確性很有要求的場(chǎng)景,是需要了解和使用for update的。
比如涉及到金錢、庫(kù)存等。一般這些操作都是很長(zhǎng)一串并且是開啟事務(wù)的。
如果庫(kù)存剛開始讀的時(shí)候是1,而立馬另一個(gè)進(jìn)程進(jìn)行了update將庫(kù)存更新為0了,而事務(wù)還沒(méi)有結(jié)束,會(huì)將錯(cuò)的數(shù)據(jù)一直執(zhí)行下去,就會(huì)有問(wèn)題。
所以需要for upate 進(jìn)行數(shù)據(jù)加鎖防止高并發(fā)時(shí)候數(shù)據(jù)出錯(cuò)。
記住一個(gè)原則:一鎖二判三更新
for update如何使用
使用姿勢(shì):
select * from table where xxx for update
for update的鎖表
InnoDB默認(rèn)是行級(jí)別的鎖,當(dāng)有明確指定的主鍵時(shí)候,是行級(jí)鎖。否則是表級(jí)別。
例子:
假設(shè)表foods ,存在有id跟name、status三個(gè)字段,id是主鍵,status有索引。
例1: (明確指定主鍵,并且有此記錄,行級(jí)鎖)
SELECT * FROM foods WHERE id=1 FOR UPDATE; SELECT * FROM foods WHERE id=1 and name='咖啡色的羊駝' FOR UPDATE;
例2: (明確指定主鍵/索引,若查無(wú)此記錄,無(wú)鎖)
SELECT * FROM foods WHERE id=-1 FOR UPDATE;
例3: (無(wú)主鍵/索引,表級(jí)鎖)
SELECT * FROM foods WHERE name='咖啡色的羊駝' FOR UPDATE;
例4: (主鍵/索引不明確,表級(jí)鎖)
SELECT * FROM foods WHERE id<>'3' FOR UPDATE; SELECT * FROM foods WHERE id LIKE ‘3' FOR UPDATE;
for update的注意點(diǎn)
1.for update 僅適用于InnoDB,并且必須開啟事務(wù),在begin與commit之間才生效。
2.要測(cè)試for update的鎖表情況,可以利用MySQL的Command Mode,開啟二個(gè)視窗來(lái)做測(cè)試。
for update的疑問(wèn)點(diǎn)
當(dāng)開啟一個(gè)事務(wù)進(jìn)行for update的時(shí)候,另一個(gè)事務(wù)也有for update的時(shí)候會(huì)一直等著,直到第一個(gè)事務(wù)結(jié)束嗎?
答:會(huì)的。除非第一個(gè)事務(wù)commit或者rollback或者斷開連接,第二個(gè)事務(wù)會(huì)立馬拿到鎖進(jìn)行后面操作。
如果沒(méi)查到記錄會(huì)鎖表嗎?
答:會(huì)的。表級(jí)鎖時(shí),不管是否查詢到記錄,都會(huì)鎖定表。
for update和for update nowait區(qū)別(前者阻塞其他事務(wù),后者拒絕其他事務(wù))
for update鎖住表或者鎖住行,只允許當(dāng)前事務(wù)進(jìn)行操作(讀寫),其他事務(wù)被阻塞,直到當(dāng)前事務(wù)提交或者回滾,被阻塞的事務(wù)自動(dòng)執(zhí)行
for update nowait 鎖住表或者鎖住行,只允許當(dāng)前事務(wù)進(jìn)行操作(讀寫),其他事務(wù)被拒絕,事務(wù)占據(jù)的statement連接也會(huì)被斷開
mysql排它鎖(FOR UPDATE) 場(chǎng)景
場(chǎng)景一
當(dāng)前使用for UPDATE查詢,其他地方查詢 -- 其他地方也使用for UPDATE會(huì)堵塞,其他地方未使用for UPDATE不會(huì)堵塞
1. 當(dāng)前A(不區(qū)分是否為事務(wù)里)使用for UPDATE查詢
SELECT * FROM saas_employee_label_person where id = 1 for UPDATE
1.1 其他地方B(不在上一個(gè)連接里或事務(wù)里,不區(qū)分是否為事務(wù)里)使用for UPDATE 查詢(需要獲取鎖)
SELECT * FROM saas_employee_label_person where id = 1 for UPDATE
會(huì)發(fā)生堵塞等待前一個(gè)A鎖釋放(A事務(wù)提交,或者A結(jié)束運(yùn)行(A為非事務(wù)場(chǎng)景))
1.2 其他地方C(不區(qū)分是否為事務(wù)里)不使用for UPDATE 查詢(無(wú)需獲取鎖)
SELECT * FROM saas_employee_label_person where id = 1
不會(huì)堵塞,可以查詢
場(chǎng)景二
當(dāng)前使用for UPDATE查詢,其他地方UPDATE更新 -- 會(huì)堵塞等待
2. 當(dāng)前A(不區(qū)分是否為事務(wù)里)使用for UPDATE查詢
SELECT * FROM saas_employee_label_person where id = 1 for UPDATE
2.1 其他地方B(不區(qū)分是否為事務(wù)里)使用UPDATE更新數(shù)據(jù)
UPDATE saas_employee_label_person set employee_id = 1111 where id = 1;
會(huì)發(fā)生堵塞等待前一個(gè)A鎖釋放(A事務(wù)提交,或者A結(jié)束運(yùn)行(A為非事務(wù)場(chǎng)景))
場(chǎng)景三
當(dāng)前事務(wù)使用UPDATE更新,其他地方使用for UPDATE查詢 -- 會(huì)堵塞等待
3. 當(dāng)前事務(wù)A 使用UPDATE更新
BEGIN; UPDATE saas_employee_label_person set employee_id = 11121 where id = 1;
3.1 其他地方B(不區(qū)分是否為事務(wù)里)使用 for UPDATE查詢
SELECT * FROM saas_employee_label_person where id = 1 for UPDATE
會(huì)發(fā)生堵塞等待前一個(gè)事務(wù)A提交才可以獲得鎖
場(chǎng)景四
當(dāng)前非事務(wù)使用UPDATE更新,其他地方使用for UPDATE查詢 -- 不會(huì)堵塞
4. 當(dāng)前A(非事務(wù)下) 使用UPDATE更新
UPDATE saas_employee_label_person set employee_id = 11121 where id = 1;
4.1 其他地方B(不區(qū)分是否為事務(wù)里)使用 for UPDATE查詢
SELECT * FROM saas_employee_label_person where id = 1 for UPDATE
不會(huì)堵塞,前一個(gè)update先執(zhí)行完,所以不影響,這里一定是update先執(zhí)行完在走for UPDATE查詢的場(chǎng)景,否者就是場(chǎng)景二了
場(chǎng)景五
當(dāng)前普通查詢,其他地方使用for UPDATE查詢 -- 不影響,不會(huì)堵塞
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- MySQL for update鎖表還是鎖行校驗(yàn)(過(guò)程詳解)
- MySQL中select...for update鎖表
- mysql中的limit 1 for update的鎖類型
- mysql行鎖(for update)解決高并發(fā)問(wèn)題
- Mysql中的select ...for update
- Mysql查詢時(shí)如何使用for update行鎖還是表鎖
- Mysql?for?update導(dǎo)致大量行鎖的問(wèn)題
- MySQL SELECT?...for?update的具體使用
- mysql事務(wù)select for update及數(shù)據(jù)的一致性處理講解
- MySQL中FOR UPDATE的具體用法
相關(guān)文章
Mysql優(yōu)化調(diào)優(yōu)中兩個(gè)重要參數(shù)table_cache和key_buffer
這篇文章主要介紹了Mysql優(yōu)化調(diào)優(yōu)中兩個(gè)重要參數(shù)table_cache和key_buffer,需要的朋友可以參考下2014-12-12pymysql操作mysql數(shù)據(jù)庫(kù)的方法
這篇文章主要介紹了pymysql簡(jiǎn)單操作mysql數(shù)據(jù)庫(kù)的方法,主要講的是一些基礎(chǔ)的pymysql操作mysql數(shù)據(jù)庫(kù)的方法,結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下2023-04-04sql語(yǔ)句示例之case?when作為where條件
這篇文章主要給大家介紹了關(guān)于sql語(yǔ)句示例之case?when作為where條件的相關(guān)資料,在SQL語(yǔ)句中CASE WHEN子句是根據(jù)條件表達(dá)式的結(jié)果來(lái)執(zhí)行不同的邏輯操作,它使用在WHERE子句中,以根據(jù)特定的條件在查詢結(jié)果中過(guò)濾數(shù)據(jù),需要的朋友可以參考下2023-08-08詳解MySQL主從復(fù)制實(shí)戰(zhàn) - 基于日志點(diǎn)的復(fù)制
這篇文章主要介紹了詳解MySQL主從復(fù)制實(shí)戰(zhàn) - 基于日志點(diǎn)的復(fù)制,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03mysql橫向轉(zhuǎn)縱向、縱向轉(zhuǎn)橫向排列的方法
這篇文章主要介紹了mysql橫向轉(zhuǎn)縱向、縱向轉(zhuǎn)橫向排列的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10