MYSQL悲觀鎖及樂(lè)觀鎖方式
MySQL支持兩種鎖機(jī)制:悲觀鎖和樂(lè)觀鎖。
悲觀鎖
悲觀鎖是指在執(zhí)行讀寫操作之前先獲取鎖,保證在操作完成之前其他線程無(wú)法修改數(shù)據(jù)。
舉個(gè)例子:
假設(shè)有一個(gè)銀行轉(zhuǎn)賬的業(yè)務(wù)場(chǎng)景,其中涉及到兩個(gè)賬戶的金額操作,為了避免數(shù)據(jù)沖突和并發(fā)問(wèn)題,可以采用悲觀鎖來(lái)實(shí)現(xiàn)。
悲觀鎖在MySQL中主要有兩種實(shí)現(xiàn)方式:
1.通過(guò)SELECT ... FOR UPDATE語(yǔ)句實(shí)現(xiàn)
該語(yǔ)句可以將待更新的行加鎖,保證其他事務(wù)無(wú)法在該行加鎖之前對(duì)其進(jìn)行修改操作。
例如:
假設(shè)有一個(gè)用戶表,其中每個(gè)用戶有一個(gè)余額字段,現(xiàn)在需要將某個(gè)用戶的余額減少100元,可以使用以下SQL語(yǔ)句:
BEGIN; SELECT balance FROM user WHERE id = 1 FOR UPDATE; UPDATE user SET balance = balance - 100 WHERE id = 1; COMMIT;
在這個(gè)例子中:
通過(guò)SELECT ... FOR UPDATE語(yǔ)句先對(duì)待更新的用戶行加鎖,確保其他事務(wù)無(wú)法在執(zhí)行更新操作之前對(duì)其進(jìn)行修改。
2.通過(guò)LOCK TABLES語(yǔ)句實(shí)現(xiàn)
該語(yǔ)句可以將整個(gè)表或者表中的某些行加鎖,確保其他事務(wù)無(wú)法對(duì)其進(jìn)行修改操作。
例如,假設(shè)有一個(gè)訂單表,其中每個(gè)訂單有一個(gè)狀態(tài)字段,現(xiàn)在需要將所有未付款的訂單狀態(tài)改為已付款,可以使用以下SQL語(yǔ)句:
LOCK TABLES order WRITE; UPDATE order SET status = 1 WHERE status = 0; UNLOCK TABLES;
在這個(gè)例子中:
通過(guò)LOCK TABLES語(yǔ)句將整個(gè)訂單表加鎖,確保其他事務(wù)無(wú)法對(duì)其進(jìn)行修改,然后執(zhí)行更新操作,最后使用UNLOCK TABLES語(yǔ)句釋放鎖。
需要注意的是,悲觀鎖機(jī)制在實(shí)現(xiàn)上通常需要使用到數(shù)據(jù)庫(kù)的鎖機(jī)制,因此在高并發(fā)場(chǎng)景下可能會(huì)導(dǎo)致性能瓶頸和死鎖問(wèn)題,所以需要謹(jǐn)慎使用。
樂(lè)觀鎖
MySQL中的樂(lè)觀鎖機(jī)制是指在執(zhí)行讀寫操作之前不加鎖,而是通過(guò)版本號(hào)或者時(shí)間戳等機(jī)制判斷數(shù)據(jù)是否被其他事務(wù)修改過(guò),從而決定是否執(zhí)行寫操作。相比于悲觀鎖,樂(lè)觀鎖的優(yōu)勢(shì)在于減少了鎖等待和死鎖等問(wèn)題,提高了并發(fā)性能。
下面舉例說(shuō)明MySQL數(shù)據(jù)庫(kù)中的樂(lè)觀鎖機(jī)制。
假設(shè)有一個(gè)用戶表,其中每個(gè)用戶有一個(gè)余額字段。
現(xiàn)在需要對(duì)某個(gè)用戶的余額進(jìn)行修改,如果余額值不變,則可以直接更新;否則需要重新讀取最新的余額值并判斷是否可以更新。
可以使用以下SQL語(yǔ)句實(shí)現(xiàn):
UPDATE user SET balance = balance - 100 WHERE id = 1 AND balance >= 100;
在這個(gè)例子中:
通過(guò)在更新語(yǔ)句中加入AND balance >= 100的條件,確保只有余額大于等于100的用戶才能被更新。
如果在執(zhí)行更新操作之前,其他事務(wù)修改了該用戶的余額值,那么執(zhí)行該更新語(yǔ)句時(shí)不會(huì)更新任何數(shù)據(jù)。
這樣就避免了臟數(shù)據(jù)和并發(fā)問(wèn)題,同時(shí)也避免了使用悲觀鎖帶來(lái)的性能問(wèn)題。
需要注意的是:
- 在使用樂(lè)觀鎖機(jī)制時(shí),需要特別關(guān)注并發(fā)沖突的問(wèn)題。
- 如果并發(fā)沖突較為頻繁,那么樂(lè)觀鎖可能會(huì)導(dǎo)致較高的重試率和性能損失。因此,樂(lè)觀鎖更適合于并發(fā)沖突較少的場(chǎng)景。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Mysql 忘記root密碼和修改root密碼的解決方法(小結(jié))
這篇文章主要介紹了Mysql 忘記root密碼和修改root密碼的解決方法(小結(jié)),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-12-12
簡(jiǎn)單解析MySQL中的cardinality異常
這篇文章主要介紹了簡(jiǎn)單解析MySQL中的cardinality異常,這個(gè)異常會(huì)導(dǎo)致索引無(wú)法使用,需要的朋友可以參考下2015-05-05
mysql中insert?into...select語(yǔ)句優(yōu)化方式
這篇文章主要介紹了mysql中insert?into...select語(yǔ)句優(yōu)化方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教<BR>2024-04-04
MySQL ClickHouse不同于SQL的語(yǔ)法介紹
CloudCanal 近期實(shí)現(xiàn)了 MySQL(RDS) 到 ClickHouse 實(shí)時(shí)同步的能力,功能包含全量數(shù)據(jù)遷移、增量數(shù)據(jù)遷移、結(jié)構(gòu)遷移能力,以及附帶的監(jiān)控、告警、HA等能力2022-11-11
MySQL中Order By多字段排序規(guī)則代碼示例
這篇文章主要介紹了MySQL中Order By多字段排序規(guī)則代碼示例,小編覺得挺不錯(cuò)的,這里給大家分享下,需要的朋友可以參考。2017-10-10
MySQL創(chuàng)建唯一索引時(shí)報(bào)錯(cuò)Duplicate?entry?*?for?key問(wèn)題
這篇文章主要介紹了MySQL創(chuàng)建唯一索引時(shí)報(bào)錯(cuò)Duplicate?entry?*?for?key問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
Windows Server2019安裝MySQL5.7.25的方法
這篇文章主要介紹了Windows Server2019安裝MySQL5.7.25,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09
MySQL創(chuàng)建數(shù)據(jù)庫(kù)的兩種方法
這篇文章主要為大家詳細(xì)介紹了MySQL創(chuàng)建數(shù)據(jù)庫(kù)的兩種方法,感興趣的小伙伴們可以參考一下2016-05-05
mysql中url時(shí)區(qū)的陷阱該如何規(guī)避詳解
最近在工作中發(fā)現(xiàn)一個(gè)問(wèn)題,是關(guān)于mysql中url時(shí)區(qū)的,發(fā)現(xiàn)這個(gè)陷阱如果大家不注意可能都會(huì)遇到,所以給大家總結(jié)下,這篇文章主要給大家介紹了關(guān)于mysql中url時(shí)區(qū)的陷阱該如何規(guī)避的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-08-08

