最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL實現(xiàn)分布式鎖的三種主流方案

 更新時間:2026年02月05日 09:07:57   作者:yangSnowy  
MySQL 實現(xiàn)分布式鎖的核心是利用數(shù)據(jù)庫的原子性、唯一性約束或行級鎖機制,保證分布式系統(tǒng)中多個節(jié)點對共享資源的互斥訪問,解決跨進程、跨服務(wù)器的并發(fā)競爭問題,以下是三種主流、可靠且覆蓋不同業(yè)務(wù)場景的實現(xiàn)方案,需要的朋友可以參考下

前言:

MySQL 實現(xiàn)分布式鎖的核心是利用數(shù)據(jù)庫的原子性、唯一性約束或行級鎖機制,保證分布式系統(tǒng)中多個節(jié)點對共享資源的互斥訪問,解決跨進程、跨服務(wù)器的并發(fā)競爭問題。以下是三種主流、可靠且覆蓋不同業(yè)務(wù)場景的實現(xiàn)方案,包含原理、完整實現(xiàn)、注意事項及適用場景對比,兼顧實用性和嚴(yán)謹(jǐn)性。

方案一:基于唯一索引的 INSERT 實現(xiàn)(最常用 / 推薦)

核心原理

利用 MySQL 唯一索引(UNIQUE INDEX)的唯一性約束實現(xiàn)鎖的互斥:為分布式鎖創(chuàng)建專用表,將鎖標(biāo)識(如資源名)設(shè)為唯一索引,多個節(jié)點同時嘗試插入同一鎖標(biāo)識的記錄時,只有一個節(jié)點能插入成功(獲鎖),其余節(jié)點因唯一索引沖突插入失敗(搶鎖失?。会尫沛i時刪除該記錄,若服務(wù)宕機未主動釋放,可通過過期時間實現(xiàn)鎖的自動釋放,避免死鎖。

1. 鎖表結(jié)構(gòu)設(shè)計(必建)

需包含鎖標(biāo)識(唯一)、過期時間、業(yè)務(wù)附加信息,同時為鎖標(biāo)識創(chuàng)建唯一索引,保證插入的原子性:

CREATE TABLE `distributed_lock` (
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `lock_key` VARCHAR(64) NOT NULL COMMENT '分布式鎖標(biāo)識(如:order:1001、stock:20)',
  `expire_time` DATETIME NOT NULL COMMENT '鎖過期時間(避免服務(wù)宕機死鎖)',
  `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_lock_key` (`lock_key`) -- 核心:唯一索引,保證同一lock_key只能插入一條
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT 'MySQL分布式鎖表';

2. 獲取鎖(INSERT 原子操作)

通過INSERT語句嘗試插入鎖記錄,插入成功即獲取鎖,插入失?。ㄎㄒ凰饕龥_突)則表示鎖已被其他節(jié)點占用。需指定合理的過期時間(大于業(yè)務(wù)執(zhí)行的最大耗時,如 5 秒、10 秒):

-- 嘗試獲取鎖:lock_key為具體資源標(biāo)識,expire_time為當(dāng)前時間+過期時長(示例:5秒)
INSERT INTO distributed_lock (lock_key, expire_time)
VALUES ('order:1001', DATE_ADD(NOW(), INTERVAL 5 SECOND));

程序處理邏輯:

執(zhí)行 INSERT 后,若受影響行數(shù) = 1 → 獲鎖成功,執(zhí)行業(yè)務(wù)邏輯;
若拋出唯一索引沖突異常(或受影響行數(shù) = 0)→ 獲鎖失敗,可重試 / 放棄。

3. 釋放鎖(DELETE 主動釋放)

業(yè)務(wù)執(zhí)行完成后,主動刪除對應(yīng) lock_key 的記錄,釋放鎖供其他節(jié)點使用:

-- 釋放鎖:根據(jù)lock_key精準(zhǔn)刪除,避免誤刪其他鎖
DELETE FROM distributed_lock WHERE lock_key = 'order:1001';

4. 鎖超時自動釋放(解決死鎖)

若服務(wù)在執(zhí)行業(yè)務(wù)時宕機 / 網(wǎng)絡(luò)中斷,無法主動執(zhí)行 DELETE 釋放鎖,此時當(dāng)expire_time小于當(dāng)前時間,鎖即失效。其他節(jié)點可通過先清理過期鎖,再嘗試獲鎖的邏輯優(yōu)化搶鎖流程:

-- 優(yōu)化版獲鎖:先刪除指定lock_key的過期鎖,再插入(保證鎖的可用性)
-- 步驟1:清理該lock_key的過期鎖(通過定時腳本等)
DELETE FROM distributed_lock WHERE lock_key = 'order:1001' AND expire_time < NOW();
-- 步驟2:嘗試插入新鎖
INSERT INTO distributed_lock (lock_key, expire_time)
VALUES ('order:1001', DATE_ADD(NOW(), INTERVAL 5 SECOND));

關(guān)鍵注意事項

過期時間必須大于業(yè)務(wù)實際最大執(zhí)行耗時,否則會出現(xiàn) “業(yè)務(wù)未執(zhí)行完,鎖已過期被其他節(jié)點獲取” 的并發(fā)問題;

釋放鎖時必須根據(jù) lock_key 精準(zhǔn)刪除,禁止無條件 DELETE 或按 id 刪除,避免誤刪其他節(jié)點的鎖;

可通過 ** 樂觀鎖(加版本號)** 進一步優(yōu)化,防止多個節(jié)點同時清理過期鎖后重復(fù)插入(極端場景);

優(yōu)點:實現(xiàn)簡單、無侵入、支持集群(主從同步即可)、天然防死鎖;缺點:高并發(fā)下可能存在輕微的鎖競爭(可通過重試機制緩解)。

方案二:基于 MySQL 自帶函數(shù) GET_LOCK/RELEASE_LOCK

核心原理

MySQL 提供了專用的鎖函數(shù)GET_LOCK(key, timeout)和RELEASE_LOCK(key),基于 ** 數(shù)據(jù)庫連接(Session)** 實現(xiàn)分布式鎖:
GET_LOCK(key, timeout):嘗試獲取名為key的鎖,超時時間為timeout秒(0 表示立即返回,-1 表示永久阻塞);同一key只能被一個連接持有,其他連接嘗試獲取會阻塞 / 失?。?br />RELEASE_LOCK(key):主動釋放名為key的鎖,釋放成功返回 1,鎖不存在返回 0,不是當(dāng)前連接持有返回 NULL;

若持有鎖的連接斷開(正常 / 異常),MySQL 會自動釋放該連接持有的所有鎖,天然防死鎖。

1. 獲取鎖(GET_LOCK)

-- 嘗試獲取鎖:key為鎖標(biāo)識,timeout=5秒(5秒內(nèi)獲取不到則返回0)
SELECT GET_LOCK('order:1001', 5);

返回值說明:

1 → 獲鎖成功;
0 → 超時未獲取到鎖;
NULL → 執(zhí)行出錯(如數(shù)據(jù)庫連接異常)。

2. 釋放鎖(RELEASE_LOCK)

-- 主動釋放鎖:key與獲取鎖時一致
SELECT RELEASE_LOCK('order:1001');

3. 強制釋放鎖(針對異常場景)

若需手動釋放其他連接持有的鎖,可通過KILL連接實現(xiàn)(需數(shù)據(jù)庫管理員權(quán)限):

-- 步驟1:查詢持有指定鎖的連接ID
SELECT PROCESSLIST_ID FROM INFORMATION_SCHEMA.PROCESSLIST 
WHERE STATE = CONCAT('Waiting for release of advisory lock for key ', QUOTE('order:1001'));
-- 步驟2:KILL該連接(自動釋放鎖)
KILL 1234; -- 1234為查詢到的連接ID

關(guān)鍵注意事項

鎖與數(shù)據(jù)庫連接強綁定:若使用連接池,需保證獲鎖、執(zhí)行業(yè)務(wù)、釋放鎖使用同一個連接(連接池不能中途回收連接);
不支持分布式集群(主從 / 多實例):GET_LOCK 的鎖信息僅存儲在當(dāng)前 MySQL 實例的內(nèi)存中,主從復(fù)制不會同步該鎖信息,多實例場景下會出現(xiàn)鎖失效;
鎖粒度為字符串 key,支持任意自定義標(biāo)識,實現(xiàn)簡單;
優(yōu)點:輕量(無需建表)、原子性強、自動釋放鎖;缺點:僅支持單機 MySQL、依賴數(shù)據(jù)庫連接、無過期時間(除連接斷開外)。

方案三:基于悲觀鎖(SELECT … FOR UPDATE)

核心原理

利用 MySQL InnoDB 引擎的行級排他鎖實現(xiàn)分布式鎖:通過SELECT … FOR UPDATE語句查詢指定資源記錄并加排他鎖,多個節(jié)點同時執(zhí)行該語句時,只有一個節(jié)點能獲取到行鎖(獲鎖成功),其余節(jié)點會被阻塞,直到鎖被釋放;鎖的釋放由事務(wù)提交 / 回滾控制,天然保證業(yè)務(wù)與鎖的一致性。

1. 前置條件

必須使用InnoDB 引擎(MyISAM 不支持事務(wù)和行級鎖);
被查詢的字段必須創(chuàng)建索引(主鍵 / 唯一索引),否則會升級為表鎖,導(dǎo)致并發(fā)性能急劇下降;
必須在顯式事務(wù)中執(zhí)行(START TRANSACTION / BEGIN),否則 SELECT 后會立即自動提交事務(wù),鎖被釋放。

2. 獲取鎖(SELECT … FOR UPDATE + 事務(wù))

先創(chuàng)建業(yè)務(wù)關(guān)聯(lián)表(或使用現(xiàn)有業(yè)務(wù)表),確保查詢字段有索引,然后在事務(wù)中加鎖:

-- 示例:基于現(xiàn)有訂單表實現(xiàn)鎖,order_id為主鍵(索引)
BEGIN; -- 開啟顯式事務(wù)
-- 嘗試獲取鎖:查詢指定order_id并加行級排他鎖,無記錄則返回空(可根據(jù)業(yè)務(wù)插入)
SELECT * FROM `order` WHERE order_id = 1001 FOR UPDATE;

程序處理邏輯:

執(zhí)行 SELECT 后,若成功返回記錄 → 獲鎖成功,執(zhí)行業(yè)務(wù)邏輯;
若被阻塞 → 等待其他節(jié)點釋放鎖,直到超時(由 innodb_lock_wait_timeout 參數(shù)控制,默認(rèn) 50 秒);
若拋出鎖等待超時異常 → 獲鎖失敗,可重試 / 放棄。

3. 釋放鎖(事務(wù)提交 / 回滾)

業(yè)務(wù)執(zhí)行完成后,提交事務(wù)釋放行鎖;若業(yè)務(wù)執(zhí)行失敗,回滾事務(wù)也會釋放鎖,避免死鎖:

COMMIT; -- 業(yè)務(wù)成功,提交事務(wù)釋放鎖
-- ROLLBACK; -- 業(yè)務(wù)失敗,回滾事務(wù)釋放鎖

關(guān)鍵注意事項

必須精準(zhǔn)查詢索引字段:若查詢條件無索引(如 SELECT … FOR UPDATE WHERE name = ‘test’,name 無索引),會觸發(fā)全表掃描并加表鎖,導(dǎo)致所有節(jié)點阻塞,嚴(yán)重影響性能;

控制事務(wù)執(zhí)行時長:事務(wù)未提交前,鎖會一直持有,需避免在事務(wù)中執(zhí)行耗時操作(如遠(yuǎn)程調(diào)用、文件 IO);
適用于業(yè)務(wù)與數(shù)據(jù)庫操作強綁定的場景:鎖的生命周期與事務(wù)一致,無需額外管理鎖的釋放;

優(yōu)點:與業(yè)務(wù)表融合(無需單獨建鎖表)、行級鎖并發(fā)性能高、事務(wù)一致性強;缺點:依賴事務(wù)、需關(guān)注索引設(shè)計、阻塞式等待(無非阻塞搶鎖方式)。

通用設(shè)計原則(必遵守)

原子性:獲鎖、釋放鎖操作必須是原子的(MySQL 的 INSERT、GET_LOCK、SELECT … FOR UPDATE 均天然保證原子性),避免多節(jié)點同時獲鎖;
超時釋放:必須設(shè)計鎖超時機制(唯一索引的 expire_time、GET_LOCK 的連接斷開、悲觀鎖的事務(wù)超時),杜絕死鎖;
精準(zhǔn)釋放:釋放鎖時必須根據(jù)鎖標(biāo)識(lock_key / 資源 ID)精準(zhǔn)操作,禁止批量刪除 / 釋放,避免誤刪其他節(jié)點的鎖;
細(xì)粒度鎖:鎖的標(biāo)識需盡可能細(xì)(如 order:1001 而非 order),減少鎖競爭,提高并發(fā)性能;
異常處理:業(yè)務(wù)執(zhí)行過程中若出現(xiàn)異常(如宕機、網(wǎng)絡(luò)中斷、超時),需保證鎖能被自動釋放,不影響后續(xù)節(jié)點搶鎖;
重試機制:獲鎖失敗時,可增加有限次數(shù)的重試邏輯(加隨機延遲),避免瞬時競爭導(dǎo)致的業(yè)務(wù)失敗,同時防止無限重試壓垮數(shù)據(jù)庫。

總結(jié)

首選方案:基于唯一索引的 INSERT 實現(xiàn),兼顧實現(xiàn)簡單、集群支持、防死鎖,適配 90% 以上的分布式鎖場景,是工業(yè)界主流選擇;

輕量單機場景:選擇GET_LOCK/RELEASE_LOCK,無需建表,操作便捷,但僅支持單機 MySQL;

業(yè)務(wù)與數(shù)據(jù)庫強綁定場景:選擇悲觀鎖 SELECT … FOR UPDATE,利用行級鎖保證事務(wù)與鎖的一致性,需重點關(guān)注索引和事務(wù)時長;

無論選擇哪種方案,都必須遵守原子性、超時釋放、精準(zhǔn)釋放三大核心原則,否則會出現(xiàn)鎖失效、死鎖、并發(fā)沖突等問題。

補充:MySQL 分布式鎖適用于并發(fā)量中等、對性能要求不是極致的場景;若為超高并發(fā)(如每秒數(shù)萬次搶鎖),建議選擇 Redis/ZooKeeper 分布式鎖,性能和可靠性更優(yōu)。

到此這篇關(guān)于MySQL實現(xiàn)分布式鎖的三種主流方案的文章就介紹到這了,更多相關(guān)MySQL實現(xiàn)分布式鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySql 8.0.11-Winxp64(免安裝版)配置教程

    MySql 8.0.11-Winxp64(免安裝版)配置教程

    這篇文章主要介紹了MySql 8.0.11-Winxp64(免安裝版)配置教程,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2018-05-05
  • MySQL 如何連接對應(yīng)的客戶端進程

    MySQL 如何連接對應(yīng)的客戶端進程

    這篇文章主要介紹了MySQL 如何連接對應(yīng)的客戶端進程,幫助大家更好的理解和學(xué)習(xí)MySQL,感興趣的朋友可以了解下
    2020-11-11
  • MySQL root密碼的重置方法

    MySQL root密碼的重置方法

    這篇文章主要介紹了MySQL root密碼的重置方法,幫助大家更好的理解和學(xué)習(xí)使用MySQL,感興趣的朋友可以了解下
    2021-04-04
  • mysql如何設(shè)置主從數(shù)據(jù)庫的同步

    mysql如何設(shè)置主從數(shù)據(jù)庫的同步

    這篇文章主要介紹了mysql如何設(shè)置主從數(shù)據(jù)庫的同步問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • mysql使用 performance_schema 進行性能監(jiān)控

    mysql使用 performance_schema 進行性能監(jiān)控

    MySQL5.7及以上版本引入的performance_schema是一個高效的性能監(jiān)控工具,替代了舊的SHOWPROFILES,它通過系統(tǒng)表實時收集SQL執(zhí)行、鎖等待、I/O等性能數(shù)據(jù),提供了詳細(xì)的監(jiān)控功能,下面就來詳細(xì)的介紹一下,感興趣的可以了解一下
    2026-03-03
  • mysql巡檢腳本(必看篇)

    mysql巡檢腳本(必看篇)

    下面小編就為大家?guī)硪黄猰ysql巡檢腳本(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • MySQL主從同步與分庫分表原理及實現(xiàn)方法

    MySQL主從同步與分庫分表原理及實現(xiàn)方法

    MySQL主從同步和分庫分表技術(shù)是解決高并發(fā)和大數(shù)據(jù)量問題的關(guān)鍵,本文詳細(xì)解析了這兩項技術(shù)的原理、實現(xiàn)方法及最佳實踐,幫助讀者構(gòu)建高性能的MySQL架構(gòu),感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • mysql 5.7.13 winx64安裝配置教程

    mysql 5.7.13 winx64安裝配置教程

    這篇文章主要為大家分享了windows下mysql 5.7.13winx64安裝配置教程,總結(jié)在安裝mysql5.7時遇到的坑,感興趣的朋友可以參考一下
    2016-12-12
  • MySQL授予用戶權(quán)限命令詳解

    MySQL授予用戶權(quán)限命令詳解

    這篇文章主要給大家介紹了關(guān)于MySQL授予用戶權(quán)限命令的相關(guān)資料,授權(quán)就是為某個用戶賦予某些權(quán)限,例如可以為新建的用戶賦予查詢所有數(shù)據(jù)庫和表的權(quán)限,需要的朋友可以參考下
    2023-11-11
  • Mysql循環(huán)插入數(shù)據(jù)的實現(xiàn)

    Mysql循環(huán)插入數(shù)據(jù)的實現(xiàn)

    這篇文章主要介紹了Mysql循環(huán)插入數(shù)據(jù)的實現(xiàn)過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08

最新評論

朝阳区| 恩平市| 咸丰县| 油尖旺区| 印江| 荃湾区| 什邡市| 南郑县| 旌德县| 石首市| 郁南县| 钟祥市| 赤壁市| 廉江市| 娄底市| 莱西市| 遂昌县| 新巴尔虎右旗| 晋城| 图木舒克市| 涪陵区| 揭东县| 常熟市| 库车县| 南充市| 齐齐哈尔市| 乾安县| 洛隆县| 平舆县| 和顺县| 台山市| 五大连池市| 遂宁市| 平定县| 光泽县| 彝良县| 安徽省| 咸丰县| 凤凰县| 纳雍县| 昔阳县|