在分布式系統中,多個進程可能會同時對同一資源進行操作,如果沒有同步機制,就會造成數據不一致問題。為了避免這種情況,需要分布式鎖。Redis 是常見的實現方式,但在某些場景下,我們也可以使用 MySQL 來實現分布式鎖。
一、MySQL 實現分布式鎖的方式
1. 基于 SELECT ... FOR UPDATE
在數據庫中設計一張鎖表,例如
lock_table
,其中包含resource
字段表示鎖的資源。當某個進程想要獲取鎖時,它執行一條帶有事務的
select ... for update
語句,查詢指定的resource
。由于
for update
會對該行加行級排他鎖,因此同一時間只有一個事務能夠獲取成功。業務執行完后,提交事務,釋放鎖。
這種方式依賴 事務 + 行鎖,實現簡單,但如果事務未提交,鎖就會一直被持有,可能導致阻塞。
2. 基于唯一索引插入
在數據庫中建立一張鎖表,
resource
字段設置為唯一索引。當進程嘗試獲取鎖時,插入一條
resource = xxx
的記錄:如果插入成功,說明鎖獲取成功。
如果插入失敗(因為唯一約束沖突),說明鎖已被占用。
釋放鎖時,刪除對應的
resource
記錄。
這種方式實現的是 非阻塞鎖,適合對性能有一定要求的場景。
二、存在的問題
性能較低:相比 Redis 內存操作,MySQL 的鎖實現基于磁盤/事務,效率偏低。
死鎖風險:如果事務未提交或連接異常,可能導致鎖長時間不釋放。
可擴展性差:MySQL 適合小規模場景,一旦分布式規模擴大,性能瓶頸明顯。
三、適用場景
對一致性要求極高的場景,可以用 MySQL 鎖來保證嚴格的事務隔離。
數據規模和并發量不大,且業務已經高度依賴 MySQL 的情況下。
四、總結
MySQL 分布式鎖的兩種實現方式:
基于事務的
select ... for update
(阻塞鎖)基于唯一索引插入(非阻塞鎖)
雖然可以用 MySQL 實現分布式鎖,但實際生產環境更多推薦 Redis 或 ZooKeeper,因為它們在 性能、可用性和可靠性 上更適合大規模分布式場景。