【MySQL 死鎖:從 “業務卡頓“ 到 “根因定位“ 的實戰指南】

MySQL 死鎖:從 “業務卡頓” 到 “根因定位” 的實戰指南

后端開發必看:MySQL死鎖排查與預防全攻略

線上系統突然報出Deadlock found when trying to get lock; try restarting transaction,用戶操作卡頓甚至超時,排查時卻對著一堆日志無從下手?這篇文章幫你徹底搞定MySQL死鎖問題!

一、先搞懂:死鎖的"本質"和"必要條件"

很多人把"鎖等待"當成死鎖,其實二者完全不同:

  • 鎖等待是"一個事務等另一個事務釋放鎖"(比如事務A沒提交,事務B等著改同一行數據),等事務A提交后,事務B就能繼續
  • 死鎖是"多個事務互相等對方釋放鎖",陷入無限循環,最后MySQL只能"犧牲"一個事務來打破僵局

死鎖的"4個必要條件"

MySQL死鎖的產生,必須同時滿足4個條件(少一個都不行),搞懂這4點,就能明白死鎖的"軟肋"在哪里:

  1. 互斥條件:鎖資源是"獨占的",一個事務拿了鎖,其他事務只能等(比如行鎖,事務A鎖住一行后,事務B不能再拿同一行的寫鎖)
  2. 持有并等待條件:事務已經拿了至少一個鎖,又在等其他事務持有的鎖(比如事務A拿了行1的鎖,又等著拿行2的鎖,同時事務B拿了行2的鎖,等著拿行1的鎖)
  3. 不可剝奪條件:事務拿到的鎖不能被"搶"走,只能自己釋放(比如事務A拿了鎖,除非它主動提交/回滾,否則其他事務不能強制讓它釋放)
  4. 循環等待條件:多個事務形成"環形等待鏈"(比如A等B的鎖,B等C的鎖,C等A的鎖)

既然死鎖需要4個條件同時成立,那預防死鎖的核心思路就很明確:打破其中一個條件(比如避免循環等待、減少"持有并等待"的時間)。

死鎖和"鎖等待超時"的區別

很多同學會把Lock wait timeout exceeded(鎖等待超時)和死鎖搞混,其實二者的觸發機制完全不同:

  • 鎖等待超時:事務A持有鎖,事務B一直等A釋放,等了超過innodb_lock_wait_timeout(默認50秒)還沒等到,就會報這個錯(是"單方面等待超時")
  • 死鎖:多個事務互相等待,MySQL的"死鎖檢測器"(每隔一段時間運行)發現了循環等待,就會主動選擇一個"代價小"的事務回滾,報Deadlock found...(是"雙向循環等待,MySQL主動干預")

簡單說:鎖等待是"一個等一個,等不及了";死鎖是"互相等,誰也走不了,MySQL強行拆局"。

二、3個真實場景:死鎖是怎么"造"出來的?

死鎖不是憑空產生的,幾乎都是"業務邏輯 + SQL執行順序"共同導致的。下面3個場景你可能或多或少遇見過,我們逐一拆解死鎖的產生過程。

場景1:"交叉更新"引發的死鎖(最常見)

業務背景:電商訂單系統,用戶支付后需要"扣減庫存"和"更新訂單狀態",兩個事務分別操作兩行數據,但更新順序相反。

事務1(用戶A支付)

-- 步驟1:扣減商品1庫存
UPDATE product_stock SET stock = stock - 1 WHERE product_id = 1;
-- 步驟2:更新訂單1001狀態為"已支付"
UPDATE orders SET status = 'PAID' WHERE order_id = 1001;

事務2(用戶B支付)

-- 步驟1:更新訂單1001狀態為"已支付"
UPDATE orders SET status = 'PAID' WHERE order_id = 1001;
-- 步驟2:扣減商品1庫存
UPDATE product_stock SET stock = stock - 1 WHERE product_id = 1;

死鎖產生過程

  1. 事務1執行"扣減庫存",拿到product_stock表中product_id=1的行鎖
  2. 同時,事務2執行"更新訂單",拿到orders表中order_id=1001的行鎖
  3. 事務1繼續執行"更新訂單",需要orders表中order_id=1001的行鎖,但這把鎖被事務2拿著,于是事務1開始等
  4. 事務2繼續執行"扣減庫存",需要product_stock表中product_id=1的行鎖,但這把鎖被事務1拿著,于是事務2開始等
  5. 此時,事務1等事務2的鎖,事務2等事務1的鎖 —— 形成循環等待,死鎖產生

為什么會這樣:兩個事務操作的是"同一批資源"(庫存行 + 訂單行),但更新的順序相反,滿足了"持有并等待"和"循環等待"兩個條件。

場景2:"間隙鎖"引發的死鎖(容易被忽略)

業務背景:用戶表userage字段(無索引),兩個事務同時按age范圍更新數據,InnoDB的"間隙鎖"可能導致死鎖。

事務1

-- 更新age在10-20之間的用戶狀態
UPDATE user SET status = 1 WHERE age BETWEEN 10 AND 20;

事務2

-- 更新age在15-25之間的用戶狀態
UPDATE user SET status = 1 WHERE age BETWEEN 15 AND 25;

死鎖產生過程

  1. InnoDB中,若查詢條件是"范圍"且字段無索引,會觸發"間隙鎖"(鎖定一個范圍的"間隙",防止幻讀)
  2. 事務1執行時,age BETWEEN 10 AND 20會鎖定(10,20)之間的間隙(包括邊界)
  3. 事務2執行時,age BETWEEN 15 AND 25會鎖定(15,25)之間的間隙,這兩個范圍有重疊(15-20)
  4. 此時,事務1可能需要訪問事務2鎖定的間隙(比如15-20),事務2也需要訪問事務1鎖定的間隙,雙方互相等待,觸發死鎖

為什么會這樣:間隙鎖的"范圍重疊"導致了循環等待,而且很多人容易忽略"無索引時范圍查詢會加間隙鎖"這個特性,排查時往往想不到是鎖的范圍出了問題。

場景3:"事務長 + 鎖競爭"引發的死鎖(高并發下常見)

業務背景:秒殺系統,高并發下多個事務同時"創建訂單→扣減庫存→記錄日志",事務執行時間長,持有鎖的時間也長。

事務流程(每個秒殺請求)

-- 步驟1:創建訂單(寫orders表)
INSERT INTO orders (order_id, user_id, goods_id) VALUES (...);
-- 步驟2:扣減庫存(更新goods表)
UPDATE goods SET stock = stock - 1 WHERE goods_id = 100;
-- 步驟3:記錄秒殺日志(寫seckill_log表)
INSERT INTO seckill_log (log_id, order_id) VALUES (...);
-- 步驟4:(業務邏輯處理,比如調用其他服務,耗時1-2秒)
-- 步驟5:提交事務
COMMIT;

死鎖產生過程

  1. 高并發下,事務A執行到步驟2(扣減庫存,持有goods表行鎖),但因為步驟4有業務邏輯,沒及時提交
  2. 事務B也執行到步驟2,需要goods表的行鎖,開始等事務A釋放
  3. 事務C執行步驟1(創建訂單),持有orders表的行鎖,繼續執行步驟2時,也開始等事務A釋放goods表的鎖
  4. 此時,事務A可能因為某種原因(比如需要查詢訂單狀態),嘗試訪問事務C持有的orders表行鎖,而事務C在等事務A的goods表行鎖 —— 形成循環等待,死鎖產生

為什么會這樣:事務太長(步驟4耗時)導致鎖持有時間久,高并發下鎖競爭激烈,原本"單一方向"的等待可能因為"事務回查資源"變成循環等待。

三、死鎖排查:3個工具 + 1個核心日志

遇到死鎖別慌,MySQL自帶了排查工具,關鍵是要找到"死鎖時各事務持有了什么鎖、在等什么鎖"。掌握下面3個工具和1個核心日志,就能快速定位死鎖根因。

1. 實時查看死鎖:show engine innodb status

這是排查死鎖的"第一手資料",執行后能看到最近一次死鎖的詳細信息(包括事務ID、SQL語句、鎖信息等)。

操作步驟:在MySQL客戶端執行:

show engine innodb status\G;

關鍵信息解讀(以場景1的交叉更新為例)

------------------------
LATEST DETECTED DEADLOCK
------------------------
2024-05-20 10:00:00
*** (1) TRANSACTION:
TRANSACTION 12345, ACTIVE 2 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 10, OS thread handle 1234, query id 5678 localhost root updating
UPDATE orders SET status = 'PAID' WHERE order_id = 1001*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 10 page no 3 n bits 72 index PRIMARY of table `test`.`orders` trx id 12345 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0*** (2) TRANSACTION:
TRANSACTION 12346, ACTIVE 2 sec starting index read
mysql tables in use 1, locked 1
2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 11, OS thread handle 5678, query id 5679 localhost root updating
UPDATE product_stock SET stock = stock - 1 WHERE product_id = 1*** (2) HOLDING THE LOCK(S):
RECORD LOCKS space id 10 page no 3 n bits 72 index PRIMARY of table `test`.`orders` trx id 12346 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 11 page no 4 n bits 72 index PRIMARY of table `test`.`product_stock` trx id 12346 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0*** WE ROLL BACK TRANSACTION (1)

重點看這幾點

  • TRANSACTION 12345TRANSACTION 12346:兩個死鎖的事務ID
  • 每個事務下的UPDATE語句:能看到事務在執行什么操作
  • WAITING FOR THIS LOCK TO BE GRANTED:事務在等什么鎖(比如事務12345在等orders表的X鎖)
  • HOLDING THE LOCK(S):事務已經持有什么鎖(比如事務12346已經持有orders表的X鎖)
  • 最后一行:MySQL選擇回滾哪個事務(這里回滾了事務12345)

通過這些信息,能快速還原"誰持有什么鎖、在等什么鎖",進而定位到業務代碼中的SQL順序問題。

2. 監控鎖等待:information_schema.innodb_locks和innodb_lock_waits

如果死鎖不是"實時發生",而是偶爾出現,可以通過這兩個系統表查看當前的"鎖持有情況"和"鎖等待情況"。

常用查詢語句

-- 查看當前持有鎖的情況
SELECT * FROM information_schema.innodb_locks;-- 查看當前鎖等待的情況(誰在等誰的鎖)
SELECT r.trx_id waiting_trx_id,  -- 等待鎖的事務IDr.trx_mysql_thread_id waiting_thread,  -- 等待鎖的線程IDr.trx_query waiting_query,  -- 等待鎖的SQLb.trx_id blocking_trx_id,  -- 持有鎖的事務IDb.trx_mysql_thread_id blocking_thread,  -- 持有鎖的線程IDb.trx_query blocking_query  -- 持有鎖的SQL
FROM information_schema.innodb_lock_waits w
JOIN information_schema.innodb_trx b ON w.blocking_trx_id = b.trx_id
JOIN information_schema.innodb_trx r ON w.requesting_trx_id = r.trx_id;

結果解讀innodb_lock_waits的結果會清晰顯示"等待事務ID、等待的SQL、持有鎖的事務ID、持有鎖的SQL",比如場景1中,會看到"事務12345在等事務12346的鎖,事務12346在等事務12345的鎖",直接印證循環等待。

3. 開啟死鎖日志:innodb_print_all_deadlocks(推薦線上開啟)

show engine innodb status只能看到"最近一次死鎖",如果死鎖頻繁發生,可能會覆蓋之前的記錄。開啟innodb_print_all_deadlocks后,MySQL會把所有死鎖信息寫入錯誤日志(error log),方便后續分析。

開啟方式

  1. 臨時開啟(重啟MySQL后失效):

    set global innodb_print_all_deadlocks = 1;
    
  2. 永久開啟(修改my.cnf):

    [mysqld]
    innodb_print_all_deadlocks = 1
    

日志位置:錯誤日志的位置可以通過show variables like 'log_error';查看,通常在/var/log/mysql/error.log(Linux)或C:\ProgramData\MySQL\MySQL Server 8.0\Data\XXX.err(Windows)。

日志中會記錄每次死鎖的詳細信息(和show engine innodb status的死鎖部分一致),方便追溯歷史死鎖。

四、死鎖預防:5個實戰方案(從代碼到配置)

排查死鎖是"事后補救",預防死鎖才是"治本之策"。結合前面的死鎖產生原因和條件,這5個方案能有效減少死鎖發生的概率。

1. 統一資源訪問順序(打破循環等待)

這是預防"交叉更新"死鎖最有效的方法 —— 讓所有事務操作同一批資源時,按固定的順序訪問。

比如場景1中,兩個事務都需要操作"庫存行"和"訂單行",可以約定"先操作庫存行,再操作訂單行",無論業務邏輯如何,都嚴格遵守這個順序:

事務1(用戶A支付)

-- 步驟1:先扣減庫存(固定順序第1步)
UPDATE product_stock SET stock = stock - 1 WHERE product_id = 1;
-- 步驟2:再更新訂單(固定順序第2步)
UPDATE orders SET status = 'PAID' WHERE order_id = 1001;

事務2(用戶B支付)

-- 步驟1:先扣減庫存(和事務1順序一致)
UPDATE product_stock SET stock = stock - 1 WHERE product_id = 1;
-- 步驟2:再更新訂單(和事務1順序一致)
UPDATE orders SET status = 'PAID' WHERE order_id = 1001;

這樣一來,事務2執行步驟1時,如果事務1已經持有庫存行的鎖,事務2會等待;但事務1執行步驟2時,不會再等事務2的鎖(因為事務2還在等步驟1的鎖),不會形成循環等待,死鎖就不會產生。

實操技巧:可以給資源(比如訂單ID、商品ID)排序,按"從小到大"或"從大到小"的順序訪問,比如"先操作ID小的行,再操作ID大的行"。

2. 減少鎖持有時間(打破"持有并等待")

事務持有鎖的時間越短,鎖競爭的概率就越低,死鎖也越難發生。核心是"讓事務盡快提交",避免在事務中做"非必要操作"。

優化方案

  • 把"耗時的業務邏輯"放到事務外執行(比如調用第三方接口、復雜計算)
  • 事務中只做"必要的數據庫操作"(增刪改查),執行完立即提交
  • 避免在事務中使用SELECT ... FOR UPDATE(行級鎖)做"預查詢",除非確實需要

反例→正例

-- 反例:事務中包含耗時業務邏輯,鎖持有時間長
START TRANSACTION;
-- 步驟1:數據庫操作(拿鎖)
UPDATE goods SET stock = stock - 1 WHERE goods_id = 100;
-- 步驟2:耗時操作(調用第三方支付接口,耗時1秒)
-- 步驟3:數據庫操作
INSERT INTO orders (...) VALUES (...);
COMMIT;-- 正例:事務只包含數據庫操作,耗時操作放外面
-- 步驟1:先執行耗時操作(無鎖)
call third_party_pay(...);
-- 步驟2:事務中只做數據庫操作,快速提交
START TRANSACTION;
UPDATE goods SET stock = stock - 1 WHERE goods_id = 100;
INSERT INTO orders (...) VALUES (...);
COMMIT; -- 立即提交,釋放鎖

3. 避免間隙鎖(針對范圍查詢)

間隙鎖是InnoDB為了防止"幻讀"引入的,但在某些場景下(比如字段無索引、范圍查詢)會導致鎖范圍擴大,引發死鎖。可以通過以下方式減少間隙鎖:

  • 給查詢字段加索引:InnoDB對有索引的字段做范圍查詢時,只會鎖定"存在的行",不會鎖定間隙(除非使用FOR UPDATE且是RR隔離級別)
  • 使用RC隔離級別:InnoDB在READ COMMITTED(RC)隔離級別下,會關閉間隙鎖(除了外鍵約束和唯一性檢查),減少鎖范圍
  • 避免用"范圍條件"更新數據:如果能明確"主鍵/唯一索引條件",就別用BETWEENIN等范圍條件

示例

-- 反例:age無索引,范圍更新觸發間隙鎖
UPDATE user SET status = 1 WHERE age BETWEEN 10 AND 20;-- 正例1:給age加索引(減少間隙鎖范圍)
ALTER TABLE user ADD INDEX idx_age (age);-- 正例2:用RC隔離級別(關閉間隙鎖)
SET tx_isolation = 'READ-COMMITTED';-- 正例3:用具體條件代替范圍(如果業務允許)
UPDATE user SET status = 1 WHERE age = 10 OR age = 11 OR ...; -- 明確值

4. 合理設置事務隔離級別

InnoDB的默認隔離級別是REPEATABLE READ(RR),會啟用間隙鎖;而READ COMMITTED(RC)隔離級別下會關閉間隙鎖,雖然可能出現"不可重復讀",但在大部分業務場景下是可接受的,且能減少死鎖。

修改隔離級別

  1. 臨時修改(當前會話):

    set session transaction isolation level read committed;
    
  2. 永久修改(my.cnf):

    [mysqld]
    transaction-isolation = READ-COMMITTED
    

注意:RC隔離級別下,SELECT ... FOR UPDATE仍會鎖行,但不會鎖間隙,適合對"幻讀"要求不高的業務(如電商訂單、用戶管理)。

5. 主動重試死鎖事務(最后一道防線)

即使做了前面的預防措施,高并發下仍可能出現死鎖。此時可以在業務代碼中"捕獲死鎖異常",主動重試事務,減少對用戶的影響。

Java代碼示例

// 重試次數
private static final int MAX_RETRY = 3;public void processOrder() {int retryCount = 0;while (retryCount < MAX_RETRY) {try {// 執行事務操作transactionTemplate.execute(status -> {updateStock(); // 扣減庫存updateOrderStatus(); // 更新訂單return null;});break; // 成功則跳出循環} catch (Exception e) {// 判斷是否是死鎖異常if (e.getMessage().contains("Deadlock found when trying to get lock")) {retryCount++;log.warn("發生死鎖,第{}次重試", retryCount);// 可選:短暫休眠,避免立即重試再次沖突Thread.sleep(100);} else {// 其他異常,直接拋出throw e;}}}
}

注意:重試次數不宜過多(建議3-5次),且重試間隔可以加個"隨機值"(比如50-200ms),避免多個事務同時重試再次沖突。

五、總結:死鎖處理的"黃金流程"

遇到死鎖不用慌,記住這個"黃金流程",從排查到解決一步到位:

  1. 查日志:用show engine innodb status或錯誤日志(開啟innodb_print_all_deadlocks)獲取死鎖詳情,明確"各事務持有什么鎖、在等什么鎖"
  2. 找原因:根據鎖信息和SQL語句,判斷是"交叉更新"(順序問題)、“間隙鎖”(范圍查詢問題)還是"長事務"(鎖持有時間問題)
  3. 做優化:按場景選方案 —— 交叉更新就統一訪問順序,間隙鎖就加索引或降隔離級別,長事務就減少鎖持有時間
  4. 留后手:代碼中捕獲死鎖異常,主動重試,降低用戶感知

死鎖的本質是"資源競爭下的循環等待",只要能打破死鎖的4個必要條件中的一個,就能有效減少死鎖。實際開發中,最優先做的是"統一資源訪問順序"和"減少鎖持有時間"—— 這兩個方案成本低、效果好,大部分死鎖都能通過這兩點解決。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/98113.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/98113.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/98113.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

從虛擬化基石到云原生架構的降維打擊:用dd/mkfs玩轉namespace隔離,解鎖Docker/K8S資源密碼,看透物理機到云服務器的進化之路

本篇摘要 本文圍繞虛擬化與容器化技術展開&#xff0c;涵蓋架構演進、Docker/K8S優勢與挑戰、namespace隔離實操&#xff08;如主機名/PID隔離&#xff09;、磁盤操作&#xff08;dd/mkfs/df/mount&#xff09;等&#xff0c;對比虛擬機與容器差異&#xff0c;闡明技術原理與架…

自動化測試的概念

文章目錄自動化測試能夠取代人工測試嗎&#xff1f;回歸測試自動化分類自動化測試金字塔為啥單元測試的性價比這么高呢&#xff1f;那為啥UI自動化測試的性價比沒有組件測試的高呢&#xff1f;web自動化測試舉例引入自動化測試的準備工作自動化測試的簡單示例自動化測試能夠取代…

OSPF故障排查實戰:如何通過一條命令精準定位網絡掩碼不匹配問題

掌握display ospf error命令的解讀技巧&#xff0c;快速解決OSPF鄰接關系建立失敗難題。一、問題背景與場景引入 在網絡運維工作中&#xff0c;OSPF&#xff08;開放最短路徑優先&#xff09;協議作為主流的內部網關協議&#xff0c;其穩定運行至關重要。然而&#xff0c;在實際…

Redis----如何引入分布式鎖

一、概述首先引入分布式鎖指的是應用程序引入&#xff0c;不是Redis本身引入&#xff0c;Redis作為中間件可以作為分布式鎖的一個典型實現方案&#xff0c;同時也有一些其他的實現方案。分布式鎖指的是一個/組程序&#xff0c;使用Redis實現的話就是通過添加一個特殊的Key-Valu…

prometheus-2.42.0.linux-amd64.tar.gz 安裝配置展示

一、prometheus 1.1解壓文件 # tar -xzvf prometheus-2.42.0.linux-amd64.tar.gz -C ~/apps/ prometheus-2.42.0.linux-amd64/ prometheus-2.42.0.linux-amd64/NOTICE prometheus-2.42.0.linux-amd64/consoles/ prometheus-2.42.0.linux-amd64/consoles/index.html.example p…

Linux 標準輸入 標準輸出 標準錯誤

目錄一. 簡介二. 常見用法2.1 輸出重定向2.2 錯誤重定向2.3 同時重定向標準輸出 錯誤2.4 輸入重定向2.5 特殊設備三. 這樣設計的好處3.1 區分正常信息和錯誤信息3.2 方便調用方腳本處理3.3 與管道結合時更清晰四. 案例4.1 if判斷4.2 ls查詢一. 簡介 ?在 Linux/Unix 中&#…

零基礎新手小白快速了解掌握服務集群與自動化運維(二)Linux Journalctl命令、Journalctl日志持久化存儲

Linux提供了一個強大的日志系統&#xff0c;它可以跟蹤和記錄系統的各種活動。在這個系統中&#xff0c;journalctl是一個非常重要的工具&#xff0c;用于查詢和操作由systemd進程管理的日志。 本文將深入探討journalctl命令&#xff0c;介紹其基本使用、高級選項及示例等內容…

【學習】【js】棧數據結構

棧 棧是一種遵從后進先出&#xff08;LIFO&#xff09;原則的有序集合。新添加或待刪除的元素都保存在棧的同一端&#xff0c;稱作棧頂&#xff0c;另一端就叫棧底。在棧里&#xff0c;新元素都靠近棧頂&#xff0c;舊元素都接近棧底。 基于數組的棧 時間復雜度O(n),占用較多的…

【Linux】基本指令 · 下

alias 指令起別名為什么 ls -l 指令等價于 ll 指令呢&#xff1f;指令就是可執行程序&#xff0c;和我們自己寫的代碼編譯好的程序&#xff0c;沒有本質區別&#xff01; 指令在系統的某一個位置存在&#xff01; 執行指令前&#xff0c;現在系統中查找對應的指令指令在根目錄下…

計算機視覺(opencv)實戰二十二——指紋圖像中提取特征點,計算兩兩指紋之間的相似度

指紋識別原理與代碼實現詳解指紋識別是一種常見的生物特征識別技術&#xff0c;廣泛應用于門禁系統、手機解鎖、考勤打卡、身份認證等場景。其核心思想是&#xff1a;從指紋圖像中提取特征點&#xff0c;計算兩幅指紋之間的相似度&#xff0c;并根據相似度判斷是否為同一人。本…

Linux基礎之部署mysql數據庫

文章目錄一、環境準備二、源碼解壓與依賴三、CMake 編譯配置四、配置 MySQL權限管理修改配置文件 /etc/my.cnf五、環境變量設置六、數據庫初始化七、服務管理八、賬號密碼管理一、環境準備 yum -y install gcc gcc-c ncurses ncurses-devel bison cmakegcc / gcc-c&#xff1a…

代碼審計-PHP專題原生開發文件上傳刪除包含文件操作監控Zend源碼解密1day分析

快速分析脆弱&#xff1a;1、看文件路徑2、看代碼里面的變量&#xff08;可控&#xff09;3、看變量前后的過濾文件安全挖掘點&#xff1a;1、腳本文件名2、應用功能點3、操作關鍵字文件上傳&#xff0c;文件下載(讀取)&#xff0c;文件包含&#xff0c;文件刪除等emlog-文件上…

零基礎搭建 Hexo 博客:從本地到 GitHub Pages 全流程指南

零基礎搭建 Hexo 博客&#xff1a;從本地到 GitHub Pages 全流程指南 Hexo 是一個快速、簡潔且高效的博客框架&#xff0c;支持使用 Markdown 來編寫文章&#xff0c;并能快速生成靜態網頁&#xff0c;非常適合想要搭建個人博客的同學。本文將帶你從零開始&#xff0c;本地搭建…

Git 簡介

Git 是目前全球最流行的分布式版本控制系統&#xff08;Distributed Version Control System, DVCS&#xff09;&#xff0c;核心作用是追蹤文件修改歷史、支持多人協同開發&#xff0c;并能高效管理代碼&#xff08;或任何文本類文件&#xff09;的版本迭代。它由 Linux 內核創…

后端Web實戰-Spring原理

目錄 1. 配置優先級 2. Bean管理 2.1 獲取Bean 2.2 Bean作用域 面試題&#xff1a;Lazy是如何解決循環依賴問題的&#xff1f; 2.3 第三方Bean 3. SpringBoot原理 3.1 起步依賴 3.2 自動配置 3.2.1 概述 3.2.2 自動配置的原理及常見方案 3.2.2.1 概述 3.2.2.2 方案…

在 Qoder 等 AI 二創 IDE 里用 VS Code Remote-SSH 的“曲線連接”實戰

目標&#xff1a;讓你在 Qoder 等在線/AI 輔助 IDE 中&#xff0c;也能像本地 VS Code 一樣通過 Remote-SSH 連接到自己的遠程服務器進行開發。 前提&#xff1a;只在你擁有或被授權的服務器上使用&#xff0c;遵守所用平臺的條款與限制。兩句話說清楚 先用本地 VS Code 正常連…

python發送請求SSL驗證設置

這個錯誤通常是由于SSL/TLS握手失敗導致的&#xff0c;可能原因包括證書驗證問題、不兼容的加密協議或網絡連接中斷。以下是幾種解決方案&#xff0c;按推薦順序排列&#xff1a; 方案一&#xff1a;臨時禁用SSL驗證&#xff08;快速測試&#xff09; response requests.get(u…

工廠自動化正從 “人工堆疊” 向 “設備替代” 快速轉變

?人工進行零件排列&#xff0c;雖在操作靈活性上有一定表現&#xff0c;但實際應用中存在明顯短板&#xff0c;對工廠自動化轉型形成制約。從成本來看&#xff0c;一名工人日均工資約數百元&#xff0c;若需 5-6 名工人協同作業&#xff0c;月均人力成本易突破萬元&#xff0c…

中標麒麟7.4部署gitlab-runner

1. 部署環境 本次部署環境完全斷網。需要離線下載gitlab-runner及其依賴。 本次部署環境為中標麒麟7.4。目前機器上部署了gitlab&#xff0c;安裝了maven。 2. 部署步驟 2.1 在外部下載好依賴 我首先在騰訊云上布置了一個centos7.9的虛擬機&#xff0c;沒有安裝任何東西。 …

在 IDEA 2024 創建 Vue 項目(保姆級)

目錄 一、 前后端分離 1. 簡介 2. 實現前后端分離的常用前端框架 3. 前后端分離和動靜分離 3.1 前后端分離: 3.2 動靜分離: 二、 Vue.js概述 1. 簡介 2. SPA介紹 2.1 優點 2.2 缺點 3. MVVM介紹 3.1 示例 三、 名詞解釋 1. Node.js 2. npm 3. webpack 4. Vue…