【BUG】生產環境死鎖問題定位排查解決全過程

目錄

      • 生產環境死鎖問題定位排查解決過程
        • 0. 表面現象
        • 1. 問題分析
          • (1)數據庫連接池資源耗盡
          • (2)數據庫鎖競爭
          • (3) 代碼實現問題
        • 2. 分析解決
          • (0) 分析過程
          • (1)優化數據庫連接池配置
          • (2)優化數據庫鎖爭用
          • (3)優化應用程序
        • 3. 總結

生產環境死鎖問題定位排查解決過程

背景:訪問項目的生產頁面,發現頁面上數據加載卡頓,沒一會兒有很多接口超時的錯誤,通過查看服務日志和數據庫日志,可以確定是生產數據庫死鎖了,以下是定位分析并解決死鎖的全過程。

根據提供的報錯信息和數據庫日志,當前服務異常的原因可能是 數據庫連接池資源耗盡數據庫鎖爭用。以下是詳細分析和解決方案:


0. 表面現象
  • 頁面上所有該微服務的請求都無法響應,都是超時失敗;

1. 問題分析
(1)數據庫連接池資源耗盡
  • 報錯信息:

    Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is com.alibaba.druid.pool.GetConnectionTimeoutException: wait millis 60000, active 20, maxActive 20, creating 0, runningSqlCount 10
    
    • active 20, maxActive 20:當前連接池中的所有連接(20 個)都被占用。
    • wait millis 60000:應用程序在等待 60 秒后仍未獲取到連接,最終超時。
    • runningSqlCount 10:當前有 10 條 SQL 正在執行。
  • 原因

    • 連接池的最大連接數(maxActive)設置過小,無法滿足高并發請求。
    • 某些 SQL 查詢執行時間過長,導致連接被長時間占用。
    • 可能存在連接泄漏(未正確關閉連接)。
(2)數據庫鎖競爭
  • 數據庫日志

    00000: 2025-03-24 09:58:55 CST [4101193]: [5-1] user = postgres,db = card_online,remote = 10.246.194.141(45236) app = PostgreSQL JDBC Driver
    DETAIL:  Process holding the lock: 4094261. Wait queue: 4094260, 4094259, 4094258, 4101188, 4094257, 4101189, 4101191, 4101190, 4101192, 4101193, 4101194, 4101195, 4101197, 4101196, 4101198, 4101199, 4101200, 4101201, 4101202.
    
    • Process holding the lock:某個進程(PID: 4094261)持有鎖。
    • Wait queue:大量進程(如 4094260、4094259 等)在等待鎖。
  • 原因

    • 某個長時間運行的事務或查詢持有鎖,導致其他事務被阻塞。
    • 鎖爭用進一步加劇了連接池資源的耗盡。
(3) 代碼實現問題
  • 導致數據庫死鎖所使用的線程池代碼
@EnableAsync
@Configuration
public class AsyncPoolConfig implements AsyncConfigurer {/*** 核心線程池大小*/private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;/*** 最大可創建的線程數*/private static final int MAX_POOL_SIZE = CORE_POOL_SIZE * 5;/*** 隊列最大長度*/private static final int QUEUE_CAPACITY = 1000;/*** 線程池維護線程所允許的空閑時間*/private static final int KEEP_ALIVE_SECONDS = 300;private static final Logger log = LoggerFactory.getLogger(AsyncPoolConfig.class);// 創建線程池@Bean(name = "threadPoolTaskExecutor")public ThreadPoolTaskExecutor threadPoolTaskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setMaxPoolSize(MAX_POOL_SIZE);executor.setCorePoolSize(CORE_POOL_SIZE);executor.setQueueCapacity(QUEUE_CAPACITY);executor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS);// 線程池對拒絕任務(無線程可用)的處理策略executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());executor.setThreadNamePrefix("async-task-");return executor;}.....
}

2. 分析解決

業務背景:涉及到的目標模塊是一個每天上午10點執行的定時任務,該任務大概內容是從數據庫中根據條件查詢出相應數據,然后批量插入到另一個數據庫表中,涉及到的數據庫表數據量大概在 3000w ~ 5000W,原來該定時任務執行的太慢了,后面重構后改為使用線程池并發執行。

(0) 分析過程

根據AsyncPoolConfig 類中的實現,因為服務器是48核的,所以按照代碼中的計算公式可得:

CORE_POOL_SIZE = 96
MAX_POOL_SIZE = 480

但是該微服務使用 Druid 管理數據庫連接池,最多才20個連接,定時任務開始運行后,線程池中所有線程火力全開,數據庫連接池瞬間就被打滿了,再加上該微服務其它模塊也有數據庫連接使用的需求,導致數據庫死鎖。

(1)優化數據庫連接池配置
  • 增加連接池大小
    application.yml 中調整 Druid 連接池的配置:

    spring:datasource:druid:max-active: 50  # 增加最大連接數initial-size: 10min-idle: 10max-wait: 30000  # 減少等待超時時間
    
  • 監控連接池狀態
    使用 Druid 的監控功能,檢查連接池的使用情況:

    spring:datasource:druid:stat-view-servlet:enabled: trueurl-pattern: /druid/*login-username: adminlogin-password: admin
    

    訪問 http://<your-service>/druid,查看連接池的活躍連接、等待連接等信息。

  • 檢查連接泄漏
    確保所有數據庫連接在使用后正確關閉。可以通過 Druid 的 removeAbandoned 配置檢測泄漏連接:

    spring:datasource:druid:remove-abandoned: trueremove-abandoned-timeout: 300  # 超過 300 秒未關閉的連接會被回收
    
(2)優化數據庫鎖爭用
  • 查找持有鎖的進程
    在 PostgreSQL 中運行以下查詢,查找當前持有鎖的進程和等待鎖的進程:

    SELECTblocked_locks.pid AS blocked_pid,blocked_activity.usename AS blocked_user,blocking_locks.pid AS blocking_pid,blocking_activity.usename AS blocking_user,blocked_activity.query AS blocked_query,blocking_activity.query AS blocking_query
    FROMpg_catalog.pg_locks blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activityON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks blocking_locksON blocking_locks.locktype = blocked_locks.locktypeAND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.databaseAND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relationAND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.pageAND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tupleAND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxidAND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionidAND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classidAND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objidAND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubidAND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activityON blocking_activity.pid = blocking_locks.pid
    WHERENOT blocked_locks.granted;
    
  • 終止阻塞進程
    如果發現某個進程長時間持有鎖,可以終止該進程。可通過臨時 kill 掉阻塞進程快速恢復生產。要徹底解決掉死鎖,還是需要著手業務代碼,修改實現,破壞掉構成死鎖的條件。

    SELECT pg_terminate_backend(<blocking_pid>);
    
  • 優化慢查詢
    檢查并優化執行時間較長的 SQL 查詢,減少鎖持有時間。可以通過以下查詢查找慢查詢。或者如果你的數據庫打開了慢SQL 記錄日志,也可以通過數據庫日志結合服務日志,根據相應的執行時間查找對應的慢SQL。

    SELECTpid,usename,query,state,now() - query_start AS duration
    FROMpg_stat_activity
    WHEREstate != 'idle'AND now() - query_start > interval '5 minutes'
    ORDER BYduration DESC;
    
(3)優化應用程序
  • 調整線程池參數

    為該任務專門創建了一個線程池,其實現與原來使用的公共線程池基本相同,只是核心線程數、最大線程數、等待隊列這3個參數根據服務器配置和Druid 數據庫連接池配置進行了調整。

    因為該任務是一個定時任務,只是在每天的一個固定時間執行,大部分時間核心線程處于閑置狀態,所以核心線程數過大會消耗不必要的資源,因此 CORE_POOL_SIZE 設置成5;

    當定時任務開始執行時會有大量的數據查詢任務被丟進線程池,所以最大線程數可以設置的稍大些但一定不能超過數據庫連接池內的連接數(避免相同情況下繼續死鎖),同時也要給該微服務的其它模塊留數據庫操作的余量,因此MAX_POOL_SIZE 設置成數據庫連接池的一半大小。

    因為執行任務所反問的數據表數據量大概在 4000萬 這個級別,使用線程池進行并發執行,每個線程批量插入時的 BATCH_SIZE5000,為保證整個任務執行過程不丟失數據,于是將任務隊列的大小設置成 QUEUE_CAPACITY = 10000

    CORE_POOL_SIZE = 5
    MAX_POOL_SIZE = 20
    QUEUE_CAPACITY = 10000
    

3. 總結
  • 根本原因

    定時任務使用連接池線程數設置過大,導致定時任務執行時,數據庫連接池資源耗盡,數據庫鎖競爭造成死鎖導致大量請求被阻塞。

  • 解決方案
    kill 掉阻塞進程優先恢復生產,定位到服務中的死鎖代碼后,通過修改配置和服務代碼的實現來徹底解決問題。

    • 優化連接池配置,增加連接數并檢測連接泄漏;
    • 調整目標任務使用線程池的配置,避免其將數據庫連接池資源耗盡,并給該服務其它模塊數據庫連接留余量;

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

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

相關文章

【計算機網絡應用層】

文章目錄 計算機網絡應用層詳解一、前言二、應用層的功能三、常見的應用層協議1. HTTP/HTTPS&#xff08;超文本傳輸協議&#xff09;2. DNS&#xff08;域名系統&#xff09;3. FTP&#xff08;文件傳輸協議&#xff09;4. SMTP/POP3/IMAP&#xff08;電子郵件協議&#xff09…

Linux 虛擬化方案

一、Linux 虛擬化技術分類 1. 全虛擬化 (Full Virtualization) 特點&#xff1a;Guest OS 無需修改&#xff0c;完全模擬硬件 代表技術&#xff1a; KVM (Kernel-based Virtual Machine)&#xff1a;主流方案&#xff0c;集成到 Linux 內核 QEMU&#xff1a;硬件模擬器&…

樹莓派 5 換清華源

首先備份原設置 cp /etc/apt/sources.list ~/sources.list.bak cp /etc/apt/sources.list.d/raspi.list ~/raspi.list.bak修改配置 /etc/apt/sources.list 文件替換內容如下&#xff08;原內容刪除&#xff09; deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm …

WGAN原理及實現(pytorch版)

WGAN原理及實現 一、WGAN原理1.1 原始GAN的缺陷1.2 Wasserstein距離的引入1.3 Kantorovich-Rubinstein對偶1.4 WGAN的優化目標1.4 數學推導步驟1.5 權重裁剪 vs 梯度懲罰1.6 優勢1.7 總結 二、WGAN實現2.1 導包2.2 數據加載和處理2.3 構建生成器2.4 構建判別器2.5 訓練和保存模…

Unity網絡開發基礎 (3) Socket入門 TCP同步連接 與 簡單封裝練習

本文章不作任何商業用途 僅作學習與交流 教程來自Unity唐老獅 關于練習題部分是我觀看教程之后自己實現 所以和老師寫法可能不太一樣 唐老師說掌握其基本思路即可,因為前端程序一般不需要去寫后端邏輯 1.認識Socket的重要API Socket是什么 Socket&#xff08;套接字&#xff0…

【linux】一文掌握 ssh和scp 指令的詳細用法(ssh和scp 備忘速查)

文章目錄 入門連接執行SCP配置位置SCP 選項配置示例ProxyJumpssh-copy-id SSH keygenssh-keygen產生鑰匙類型known_hosts密鑰格式 此快速參考備忘單提供了使用 SSH 的各種方法。 參考&#xff1a; OpenSSH 配置文件示例 (cyberciti.biz)ssh_config (linux.die.net) 入門 連…

真實筆試題

文章目錄 線程題樹的深度遍歷 線程題 實現一個類支持100個線程同時向一個銀行賬戶中存入一元錢.需通過同步機制消除競態條件,當所有線程執行完成后,賬戶余額必須精確等于100元 package com.itheima.thread;public class ShowMeBug {private double balance; // 賬戶余額priva…

2.2 路徑問題專題:LeetCode 63. 不同路徑 II

動態規劃解決LeetCode 63題&#xff1a;不同路徑 II&#xff08;含障礙物&#xff09; 1. 題目鏈接 LeetCode 63. 不同路徑 II 2. 題目描述 一個機器人位于 m x n 網格的左上角&#xff0c;每次只能向右或向下移動一步。網格中可能存在障礙物&#xff08;標記為 1&#xff…

2874. 有序三元組中的最大值 II

給你一個下標從 0 開始的整數數組 。nums 請你從所有滿足 的下標三元組 中&#xff0c;找出并返回下標三元組的最大值。 如果所有滿足條件的三元組的值都是負數&#xff0c;則返回 。i < j < k(i, j, k)0 下標三元組 的值等于 。(i, j, k)(nums[i] - nums[j]) * nums[k…

【論文筆記】Llama 3 技術報告

Llama 3中的頂級模型是一個擁有4050億參數的密集Transformer模型&#xff0c;并且它的上下文窗口長度可以達到128,000個tokens。這意味著它能夠處理非常長的文本&#xff0c;記住和理解更多的信息。Llama 3.1的論文長達92頁&#xff0c;詳細描述了模型的開發階段、優化策略、模…

JVM深入原理(一+二):JVM概述和JVM功能

目錄 1. JVM概述 1.1. Java程序結構 1.2. JVM作用 1.3. JVM規范和實現 2. JVM功能 2.1. 功能-編譯和運行 2.2. 功能-內存管理 2.3. 功能-即時編譯 1. JVM概述 1.1. Java程序結構 1.2. JVM作用 JVM全稱是Java Virtual Machine-Java虛擬機 JVM作用:本質上是一個運行在…

SQL Server Integration Services (SSIS) 服務無法啟動

問題現象&#xff1a; 安裝 SQL Server 2022 后&#xff0c;SQL Server Integration Services (SSIS) 服務無法啟動&#xff0c;日志報錯 “服務無法響應控制請求”&#xff08;錯誤代碼 1067&#xff09;或 “依賴服務不存在或已標記為刪除”。 快速診斷 檢查服務狀態與依賴項…

Spring Boot 定時任務的多種實現方式

&#x1f31f; 前言 歡迎來到我的技術小宇宙&#xff01;&#x1f30c; 這里不僅是我記錄技術點滴的后花園&#xff0c;也是我分享學習心得和項目經驗的樂園。&#x1f4da; 無論你是技術小白還是資深大牛&#xff0c;這里總有一些內容能觸動你的好奇心。&#x1f50d; &#x…

Java基礎之反射的基本使用

簡介 在運行狀態中&#xff0c;對于任意一個類&#xff0c;都能夠知道這個類的所有屬性和方法&#xff1b;對于任意一個對象&#xff0c;都能夠調用它的任意屬性和方法&#xff1b;這種動態獲取信息以及動態調用對象方法的功能稱為Java語言的反射機制。反射讓Java成為了一門動…

AI產品的上層建筑:提示詞工程、RAG與Agent

上節課我們拆解了 AI 產品的基礎設施建設&#xff0c;這節課我們聊聊上層建筑。這部分是產品經理日常工作的重頭戲&#xff0c;包含提示詞、RAG 和 Agent 構建。 用 AI 客服產品舉例&#xff0c;這三者的作用是這樣的&#xff1a; 提示詞能讓客服很有禮貌。比如它會說&#x…

藍橋杯刷題記錄【并查集001】(2024)

主要內容&#xff1a;并查集 并查集 并查集的題目感覺大部分都是模板題&#xff0c;上板子&#xff01;&#xff01; class UnionFind:def __init__(self, n):self.pa list(range(n))self.size [1]*n self.cnt ndef find(self, x):if self.pa[x] ! x:self.pa[x] self.fi…

海外SD-WAN專線網絡部署成本分析

作為支撐企業國際業務的重要基石&#xff0c;海外SD-WAN專線以其獨特的成本優勢和技術特性&#xff0c;正成為企業構建高效穩定的全球網絡架構的首選方案。本文將從多維度解構海外SD-WAN專線部署的核心成本要素&#xff0c;為企業的全球化網絡布局提供戰略參考。 一、基礎資源投…

操作系統(二):實時系統介紹與實例分析

目錄 一.概念 1.1 分類 1.2 主要指標 二.實現原理 三.主流實時系統對比 一.概念 實時系統&#xff08;Real-Time System, RTS&#xff09;是一類以時間確定性為核心目標的計算機系統&#xff0c;其設計需確保在嚴格的時間約束內完成任務響應。 1.1 分類 根據時間約束的嚴…

Golang的消息中間件選型

# Golang的消息中間件選型 消息中間件的作用 消息中間件是一種用于分布式系統中應用程序之間進行通信的基礎架構工具&#xff0c;它能夠有效地解耦發送者和接收者&#xff0c;并提供高可用性和可靠性的消息傳遞機制。在Golang應用程序中&#xff0c;選擇適合的消息中間件對于構…

大模型中的參數規模與顯卡匹配

在大模型訓練和推理中&#xff0c;顯卡&#xff08;GPU/TPU&#xff09;的選擇與模型參數量緊密相關&#xff0c;需綜合考慮顯存、計算能力和成本。以下是不同規模模型與硬件的匹配關系及優化策略&#xff1a; 一、參數規模與顯卡匹配參考表 模型參數量訓練階段推薦顯卡推理階…