偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

MySQL中的八種鎖!你知道幾種?

數(shù)據(jù)庫 MySQL
在雙11期間,支付寶數(shù)據(jù)庫集群每秒處理25萬筆交易,而支撐這一切的核心技術(shù)之一就是MySQL的鎖機(jī)制。這篇文章跟大家一起聊聊MySQL的8種鎖,希望對(duì)你會(huì)有所幫助。

前言

在雙11期間,支付寶數(shù)據(jù)庫集群每秒處理25萬筆交易,而支撐這一切的核心技術(shù)之一就是MySQL的鎖機(jī)制。

很多小伙伴在工作中都遇到過這樣的場景:

  • 凌晨批量處理數(shù)據(jù)時(shí)系統(tǒng)突然卡死。
  • 高并發(fā)場景下出現(xiàn)詭異的死鎖報(bào)錯(cuò)。
  • 明明只更新一行卻導(dǎo)致全表阻塞。

這篇文章跟大家一起聊聊MySQL的8種鎖,希望對(duì)你會(huì)有所幫助。

一、鎖的本質(zhì):并發(fā)控制的基石

1.為什么需要鎖?

當(dāng)多個(gè)事務(wù)同時(shí)操作同一數(shù)據(jù)時(shí),可能引發(fā):

  • 臟讀:讀到未提交的數(shù)據(jù)
  • 不可重復(fù)讀:同事務(wù)內(nèi)兩次讀取結(jié)果不同
  • 幻讀:同條件查詢出現(xiàn)新記錄

鎖的作用:通過對(duì)數(shù)據(jù)資源加鎖,實(shí)現(xiàn)事務(wù)的隔離性(ACID中的"I")

二、鎖的分類全景圖

1.按粒度劃分

按粒度劃分為:

  • 表鎖
  • 頁鎖
  • 行鎖

2.按模式劃分

鎖類型

共享性

典型場景

共享鎖(S)

可共享

SELECT ... LOCK IN SHARE MODE

排他鎖(X)

獨(dú)占

UPDATE/DELETE/INSERT

意向共享鎖(IS)

表級(jí)標(biāo)記

準(zhǔn)備加行級(jí)S鎖前

意向排他鎖(IX)

表級(jí)標(biāo)記

準(zhǔn)備加行級(jí)X鎖前

三、行級(jí)鎖:高并發(fā)的核心戰(zhàn)場

1.記錄鎖(Record Lock)

鎖定索引記錄:

-- 事務(wù)A
BEGIN;
SELECT * FROM users WHERE id = 1 FOR UPDATE; -- 對(duì)id=1加X鎖

-- 事務(wù)B(將被阻塞)
UPDATE users SET name = 'Tom' WHERE id = 1;

底層實(shí)現(xiàn):

2.間隙鎖(Gap Lock)

鎖定索引區(qū)間(解決幻讀):

假設(shè)當(dāng)前表結(jié)構(gòu):id主鍵(當(dāng)前有id=1,5,10)

BEGIN;
SELECT * FROM users WHERE id BETWEEN 5 AND 10 FOR UPDATE;

-- 阻塞所有[5,10]區(qū)間的插入
INSERT INTO users(id) VALUES(6); -- 被阻塞!
INSERT INTO users(id) VALUES(11); -- 成功

鎖定范圍:

3.臨鍵鎖(Next-Key Lock)

記錄鎖+間隙鎖組合:

假設(shè)當(dāng)前數(shù)據(jù)庫隔離級(jí)別是RR(Repeatable Read):

BEGIN;
SELECT * FROM users WHERE id > 5 FOR UPDATE; 

-- 阻塞操作
UPDATE users SET name='A' WHERE id=10; -- 記錄鎖阻塞
INSERT INTO users(id) VALUES(6);     -- 間隙鎖阻塞

鎖范圍示意圖:

四、表級(jí)鎖:全表掃描的保護(hù)傘

1.表鎖(Table Lock)

顯式加鎖:

LOCK TABLES users WRITE; -- 獲取寫鎖
-- 執(zhí)行更新...
UNLOCK TABLES;

隱式加鎖(DDL操作自動(dòng)加鎖):

ALTER TABLE users ADD COLUMN age INT; -- 自動(dòng)加表級(jí)X鎖

2.元數(shù)據(jù)鎖(MDL)

保護(hù)表結(jié)構(gòu):

-- 會(huì)話A
BEGIN;
SELECT * FROM users; -- 獲取MDL讀鎖

-- 會(huì)話B(被阻塞)
ALTER TABLE users ADD COLUMN email VARCHAR(255);

等待鏈:

五、死鎖:高并發(fā)的終極挑戰(zhàn)

1.經(jīng)典死鎖場景

-- 事務(wù)A
BEGIN;
UPDATE accounts SET balance = balance - 100WHEREid = 1;
UPDATE accounts SET balance = balance + 100WHEREid = 2;

-- 事務(wù)B(反向操作)
BEGIN;
UPDATE accounts SET balance = balance - 100WHEREid = 2;
UPDATE accounts SET balance = balance + 100WHEREid = 1;

死鎖形成過程:

2.死鎖檢測與解決

自動(dòng)檢測:

SHOW ENGINE INNODB STATUS; 
-- 查看LATEST DETECTED DEADLOCK

手動(dòng)處理:

// Spring事務(wù)重試
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 100))
@Transactional
public void transferMoney(Long from, Long to, BigDecimal amount) {
    // 轉(zhuǎn)賬邏輯
}

六、鎖監(jiān)控與優(yōu)化實(shí)戰(zhàn)

1.鎖等待分析

-- 查看鎖等待
SELECT * FROM information_schema.INNODB_TRX;
SELECT * FROM information_schema.INNODB_LOCKS;
SELECT * FROM information_schema.INNODB_LOCK_WAITS;

2.索引優(yōu)化避免全表鎖

問題SQL:

UPDATE users SET status=1 WHERE name LIKE 'A%'; -- 無索引導(dǎo)致表鎖

優(yōu)化方案:

ALTER TABLE users ADD INDEX idx_name(name); -- 創(chuàng)建索引
UPDATE users SET status=1 WHERE name LIKE 'A%'; -- 僅加行鎖

3.鎖超時(shí)配置

# my.cnf
[mysqld]
innodb_lock_wait_timeout=50  # 默認(rèn)50秒

七、不同隔離級(jí)別的鎖差異

隔離級(jí)別

臟讀

不可重復(fù)讀

幻讀

鎖機(jī)制

讀未提交(Read Uncommitted)

可能

可能

可能

不加鎖

讀已提交(Read Committed)

不可能

可能

可能

語句級(jí)快照

可重復(fù)讀(Repeatable Read)

不可能

不可能

可能(*)

臨鍵鎖(默認(rèn))

串行化(Serializable)

不可能

不可能

不可能

全表鎖

InnoDB在RR級(jí)別通過Next-Key Lock解決幻讀問題。

八、鎖機(jī)制最佳實(shí)踐

1. 鎖優(yōu)化口訣

  • 一快:事務(wù)執(zhí)行要快。
  • 二小:鎖粒度盡量小。
  • 三避免:避免大事務(wù)、全表掃描、長等待 。

2. 不同場景鎖選擇

場景

推薦方案

精確更新單行

行級(jí)X鎖(WHERE主鍵)

范圍更新

Next-Key Lock(RR隔離級(jí)別)

全表更新

分批提交+低峰期執(zhí)行

結(jié)構(gòu)變更

PT-Online-Schema-Change工具

總結(jié)

  • 鎖是雙刃劍:保護(hù)數(shù)據(jù)一致性的同時(shí)降低并發(fā)度
  • 粒度決定性能:行鎖 > 頁鎖 > 表鎖
  • 隔離級(jí)別是基礎(chǔ):根據(jù)業(yè)務(wù)選擇合適級(jí)別(推薦RR)
  • 索引是鑰匙:80%的鎖問題可通過優(yōu)化索引解決
  • 監(jiān)控是眼睛:善用SHOW ENGINE INNODB STATUS

正如數(shù)據(jù)庫專家Michael Stonebraker所言:“The best locking strategy is no locking at all.”

最高明的鎖策略是“無鎖”,而這正是我們不斷優(yōu)化的方向。

責(zé)任編輯:姜華 來源: 蘇三說技術(shù)
相關(guān)推薦

2024-08-01 09:58:33

API性能機(jī)制

2024-04-28 14:49:31

2020-11-16 09:15:07

MYSQL

2021-08-05 07:28:25

Java實(shí)現(xiàn)方式

2021-03-03 00:01:30

Redis數(shù)據(jù)結(jié)雙向鏈表

2019-09-02 11:14:08

隔離虛擬機(jī)操作系統(tǒng)

2021-05-07 16:19:36

異步編程Java線程

2025-01-21 10:04:40

Java并發(fā)阻塞隊(duì)列

2023-10-30 11:53:37

繼承JS父類

2025-04-17 07:10:03

API架構(gòu)項(xiàng)目

2022-05-27 06:57:50

Python循環(huán)方式生成器

2022-02-10 08:57:45

分布式線程鎖

2024-11-04 09:39:08

Java?接口Thread?類

2024-04-24 11:24:43

C#數(shù)據(jù)去重

2019-12-02 10:16:46

架構(gòu)設(shè)計(jì)模式

2022-06-29 08:32:04

游標(biāo)MySQL服務(wù)器

2022-08-11 08:46:23

索引數(shù)據(jù)結(jié)構(gòu)

2024-05-10 07:44:23

C#進(jìn)程程序

2024-09-20 08:04:54

2023-12-27 12:12:35

NumPy函數(shù)數(shù)組
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)