日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql分布式安装可靠读写案列图解,高并发下的分布式锁-mysql篇

發(fā)布時間:2025/3/19 数据库 70 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql分布式安装可靠读写案列图解,高并发下的分布式锁-mysql篇 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

不管是在面試中,還是在平時的工作中,高并發(fā)永遠(yuǎn)是衡量一個web工作者能力的重要場景。本篇幅我們主要是來討論在高并發(fā)環(huán)境下我們應(yīng)該如何實現(xiàn)分布式鎖。

實現(xiàn)分布式鎖的方式有比較多,這里主要考慮如何使用mysql實現(xiàn)分布式鎖。

Mysql實現(xiàn)鎖的方法

第一種,使用mysql唯一索引來實現(xiàn):

針對這種實現(xiàn),我們只需要新建一張表,專門用來處理分布式任務(wù),比如新建一張 task的表,里面的唯一索引為 task_name 。

運行流程如下:當(dāng)多個副本同時要搶占一個任務(wù)的鎖的時候,就執(zhí)行一個插入語句(這幾個副本的task_name都是一致的),所以,當(dāng)有一個副本之行插入成功后,后續(xù)的其他插入則會由于唯一索引的問題,導(dǎo)致插入失敗。我們可以根據(jù)插入的影響條數(shù)為0 或者是1 ,判斷是否搶鎖成功。最后搶鎖成功的副本,在任務(wù)執(zhí)行結(jié)束之后,將該條記錄刪除,即把鎖刪除掉。

CREATE TABLE `tests`.`task` (

`task-name` varchar(255) NULL,

`id` int(0) NOT NULL AUTO_INCREMENT,

`ctime` timestamp(0) NULL,

`mtime` timestamp(0) NULL ON UPDATE CURRENT_TIMESTAMP(0),

PRIMARY KEY (`id`),

INDEX `uniq_idx_task_name`(`task-name`)

);

// 副本1執(zhí)行:

INSERT INTO `tests`.`task`(`task-name`, `ctime`, `mtime`) VALUES ('demo1', 1, NULL, NULL);

// 副本2同時執(zhí)行

INSERT INTO `tests`.`task`(`task-name`, `ctime`, `mtime`) VALUES ('demo1', 1, NULL, NULL);

// 以上只會有一個副本執(zhí)行成功,另一個副本會直接失敗

第二種,使用mysql的悲觀鎖

for update 和 for udpate no wait :

使用的前提:基于Innodb,并且在支持事務(wù)的情況下可以使用

當(dāng)某用戶執(zhí)行了 for update 之后,該用戶可以在提交或者放棄事務(wù)之前,對該事務(wù)進(jìn)行查詢和更新,其他用戶只能查詢但不能更新被加鎖的數(shù)據(jù)行。

** select XXXX for update 在執(zhí)行過程中可能會鎖行,也可能會鎖表 。 **

當(dāng)查詢中帶有主鍵的時候,會鎖行;

當(dāng)明確帶有(即是使用的不包括模糊查詢之類的)主鍵,但是查詢沒有結(jié)果的,不會導(dǎo)致鎖表;

當(dāng)查詢中無主鍵或者使用了like之類需要全表掃描的,會導(dǎo)致鎖住整個表;(即使查詢中沒有任何數(shù)據(jù)的時候也會導(dǎo)致鎖表)

另外,select XX for update nowait 與 只有 for update 的區(qū)別是for update ,當(dāng)另一個連接嘗試獲取到鎖的時候,會阻塞在那里等待;如果加了 nowait 的話,當(dāng)獲取不到鎖的時候會直接報錯。

// 為了方便這里借用上上面的task表

// 起一個終端,連接上數(shù)據(jù)庫,然后執(zhí)行以下:

set autocommit = 0;

select * from task for update;

// 等待一段時間后再執(zhí)行;

commit;

此時,另一個終端執(zhí)行,可以發(fā)現(xiàn),執(zhí)行 select的話,可以直接返回,但是update的話會產(chǎn)生阻塞,直到之前的事務(wù)commit(看執(zhí)行時間就可以知道)

image.png

// 如果使用for update nowait;

// 副本1執(zhí)行成功:

select * from task for update nowait;

// 副本2執(zhí)行:

mysql> select * from task for update nowait;

ERROR 3572 (HY000): Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set

//值得注意的是,for update nowait 的話,如果你執(zhí)行 update 操作的話,仍然會阻塞在那里。

第三種,使用樂觀鎖

(區(qū)分下第一種,第一種是針對單點定時任務(wù)的,這里延伸下成加鎖)

使用樂觀鎖的話,可以給表中加一個 version 字段,用于表示該行記錄的版本(如果你想要用 timestamp來做也可以,可以直接使用mysql的字段,那樣你就不用考慮該值的更新)

因此,每次更新的流程是,先 select 獲取到一個version(比如是3) 然后再進(jìn)行 update ,查詢中在原來的基礎(chǔ)上多加一個 and version = 3, 如果在select 和 update 之間有個第三方操作了數(shù)據(jù)庫并且操作成功了,此刻version變成了4,那么你進(jìn)行這次update的時候 update XXX where XXX and version = 3的時候,更新就會失敗,那么就不會影響。

結(jié)語

以上就是mysql鎖的三種方式,不過說實話,mysql的性能確實在高并發(fā)環(huán)境下,不值得期待,但是多了解下這種知識,也算是擴(kuò)寬下自己的解決問題的思路吧。

共勉

總結(jié)

以上是生活随笔為你收集整理的mysql分布式安装可靠读写案列图解,高并发下的分布式锁-mysql篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。