PostgreSQL 的 pg_advisory_lock 函數

PostgreSQL 的 pg_advisory_lock 函數

pg_advisory_lock 是 PostgreSQL 提供的一種應用級鎖機制,它不鎖定具體的數據庫對象(如表或行),而是通過數字鍵值來協調應用間的并發控制。

鎖的基本概念

PostgreSQL 提供兩種咨詢鎖(advisory lock):

  1. 會話級咨詢鎖:鎖在會話結束時自動釋放
  2. 事務級咨詢鎖:鎖在事務結束時自動釋放

主要函數列表

函數描述
pg_advisory_lock(key)獲取會話級咨詢鎖(阻塞)
pg_try_advisory_lock(key)嘗試獲取會話級咨詢鎖(非阻塞)
pg_advisory_xact_lock(key)獲取事務級咨詢鎖(阻塞)
pg_try_advisory_xact_lock(key)嘗試獲取事務級咨詢鎖(非阻塞)
pg_advisory_unlock(key)釋放會話級咨詢鎖
pg_advisory_unlock_all()釋放當前會話持有的所有咨詢鎖

函數詳解

1 pg_advisory_lock(key bigint)

功能:獲取一個會話級別的咨詢鎖(如果鎖已被其他會話持有,則阻塞等待)

參數

  • key:64位整數鎖標識

示例

SELECT pg_advisory_lock(123456);
-- 執行需要同步的操作
SELECT pg_advisory_unlock(123456);

2 pg_try_advisory_lock(key bigint)

功能:嘗試獲取會話級咨詢鎖(非阻塞,立即返回成功與否)

返回值:boolean(true表示獲取成功)

示例

DO $$
BEGINIF pg_try_advisory_lock(123456) THENRAISE NOTICE 'Lock acquired, performing work...';-- 執行受保護的操作PERFORM pg_advisory_unlock(123456);ELSERAISE NOTICE 'Could not acquire lock, skipping...';END IF;
END $$;

3 pg_advisory_xact_lock(key bigint)

功能:獲取事務級咨詢鎖(鎖在事務結束時自動釋放)

示例

BEGIN;
SELECT pg_advisory_xact_lock(123456);
-- 執行需要同步的操作
COMMIT; -- 鎖自動釋放

4 pg_try_advisory_xact_lock(key bigint)

功能:嘗試獲取事務級咨詢鎖(非阻塞)

示例

BEGIN;
SELECT pg_try_advisory_xact_lock(123456);
-- 無論是否獲取成功都繼續執行
COMMIT;

鎖的鍵值設計

咨詢鎖使用64位整數作為鍵值,有兩種使用方式:

  1. 單鍵模式:使用一個64位整數

    SELECT pg_advisory_lock(123456789);
    
  2. 雙鍵模式:使用兩個32位整數組合

    SELECT pg_advisory_lock(123, 456);
    

實際應用場景

場景1:防止定時任務重復執行

-- 在定時任務開始時檢查鎖
DO $$
BEGINIF NOT pg_try_advisory_xact_lock(987654) THENRAISE NOTICE 'Task is already running in another process';RETURN;END IF;RAISE NOTICE 'Starting scheduled task...';-- 執行定時任務邏輯-- ...COMMIT; -- 鎖自動釋放
END $$;

場景2:應用級分布式鎖

-- 應用1獲取鎖
SELECT pg_advisory_lock(555555) FROM my_table WHERE id = 1;-- 應用2嘗試獲取同樣的鎖
SELECT pg_try_advisory_lock(555555); -- 返回false-- 應用1釋放鎖
SELECT pg_advisory_unlock(555555);

場景3:確保單實例初始化

-- 系統初始化時確保只執行一次
DO $$
BEGIN-- 嘗試獲取鎖,等待最多5秒FOR i IN 1..5 LOOPIF pg_try_advisory_lock(1357924680) THEN-- 檢查是否已經初始化IF NOT EXISTS (SELECT 1 FROM system_status WHERE initialized = true) THEN-- 執行初始化INSERT INTO system_status(initialized) VALUES (true);RAISE NOTICE 'System initialized successfully';ELSERAISE NOTICE 'System already initialized';END IF;-- 顯式釋放鎖(雖然會話結束會自動釋放)PERFORM pg_advisory_unlock(1357924680);RETURN;END IF;PERFORM pg_sleep(1); -- 等待1秒END LOOP;RAISE EXCEPTION 'Could not acquire initialization lock after 5 seconds';
END $$;

監控咨詢鎖

查看當前持有的咨詢鎖

SELECT locktype, classid, objid, objsubid, mode, granted
FROM pg_locks
WHERE locktype = 'advisory';

查看所有咨詢鎖(包括已授予和等待的)

SELECT pid, locktype, mode, granted, fastpath, virtualtransaction
FROM pg_locks 
WHERE locktype = 'advisory';

注意事項

  1. 鎖釋放

    • 會話級鎖必須顯式釋放或會話結束自動釋放
    • 事務級鎖在事務結束時自動釋放
  2. 死鎖風險

    • 按固定順序獲取多個咨詢鎖以避免死鎖
    • 使用 pg_try_advisory_lock 可以降低死鎖風險
  3. 性能影響

    • 咨詢鎖比表鎖/行鎖更輕量級
    • 大量使用仍可能影響性能
  4. 集群環境

    • 咨詢鎖只在單個PostgreSQL實例內有效
    • 不適用于跨多個數據庫實例的協調
  5. 鎖標識管理

    • 建議在應用中集中管理鎖標識
    • 使用有意義的常量而非魔法數字

高級用法

超時獲取鎖

DO $$
DECLARElock_acquired BOOLEAN := false;timeout INTERVAL := '5 seconds';start_time TIMESTAMP := clock_timestamp();
BEGINWHILE (clock_timestamp() - start_time) < timeout LOOPIF pg_try_advisory_lock(424242) THENlock_acquired := true;EXIT;END IF;PERFORM pg_sleep(0.1); -- 等待100msEND LOOP;IF lock_acquired THENRAISE NOTICE 'Lock acquired after %', clock_timestamp() - start_time;-- 執行受保護的操作PERFORM pg_advisory_unlock(424242);ELSERAISE EXCEPTION 'Could not acquire lock within timeout';END IF;
END $$;

使用咨詢鎖實現隊列

-- 生產者
SELECT pg_advisory_lock(987); -- 全局寫鎖-- 插入隊列項
INSERT INTO job_queue(job_data) VALUES ('some data');SELECT pg_advisory_unlock(987);-- 消費者
SELECT pg_advisory_lock(988); -- 全局讀鎖-- 獲取并鎖定一個作業
UPDATE job_queue 
SET status = 'processing', worker_id = pg_backend_pid(),claimed_at = NOW()
WHERE id = (SELECT id FROM job_queue WHERE status = 'pending' ORDER BY created_at LIMIT 1
)
RETURNING *;SELECT pg_advisory_unlock(988);

pg_advisory_lock 是 PostgreSQL 強大的應用級同步機制,合理使用可以解決復雜的并發控制問題,但需要謹慎設計以避免死鎖和性能問題。

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

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

相關文章

SGLang 實戰介紹 (張量并行 / Qwen3 30B MoE 架構部署)

一、技術背景 隨著大語言模型&#xff08;LLM&#xff09;的飛速發展&#xff0c;如何更高效、更靈活地駕馭這些強大的模型生成我們期望的內容&#xff0c;成為了開發者們面臨的重要課題。傳統的通過拼接字符串、管理復雜的狀態和調用 API 的方式&#xff0c;在處理復雜任務時…

微服務中 本地啟動 springboot 無法找到nacos配置 啟動報錯

1. 此處的環境變量需要匹配nacos中yml配置文件名的后綴 對于粗心的小伙伴在切換【測試】【開發】環境的nacos使用時會因為這里導致項目總是無法啟動成功

Lua從字符串動態構建函數

在 Lua 中&#xff0c;你可以通過 load 或 loadstring&#xff08;Lua 5.1&#xff09;函數從字符串動態構建函數。以下是一個示例&#xff1a; 示例 1&#xff1a;基本動態函數構建 -- 動態構建一個函數 local funcStr "return function(a, b) return a b end"-…

【Python】?Python單元測試框架unittest總結

1. 本期主題&#xff1a;Python單元測試框架unittest詳解 unittest是Python內置的單元測試框架&#xff0c;遵循Java JUnit的"測試驅動開發"&#xff08;TDD&#xff09;理念&#xff0c;通過繼承TestCase類實現測試用例的模塊化組織。本文聚焦于獨立測試腳本的編寫…

【Python 實戰】---- 使用Python批量將 .ncm 格式的音頻文件轉換為 .mp3 格式

1. 前言 .ncm 格式是網易云音樂專屬的加密音頻格式,用于保護版權。這種格式無法直接播放,需要解密后才能轉換為常見的音頻格式。本文將介紹如何使用 Python 批量將 .ncm 格式的音頻文件轉換為 .mp3 格式。 2. 安裝 ncmdump ncmdump 是一個專門用于解密 .ncm 文件的工具。它…

Linux 學習筆記2

Linux 學習筆記2 一、定時任務調度操作流程注意事項 二、磁盤分區與管理添加新硬盤流程磁盤管理命令 三、進程管理進程操作命令服務管理&#xff08;Ubuntu&#xff09; 四、注意事項 一、定時任務調度 操作流程 創建腳本 vim /path/to/script.sh # 編寫腳本內容設置可執行權…

YOLO目標檢測算法

文章目錄 前言一、目標檢測算法簡介1、傳統目標檢測算法&#xff08;1&#xff09;R-CNN算法簡介&#xff08;2&#xff09;Fast R-CNN算法簡介&#xff08;3&#xff09;Faster R-CNN算法簡介 2、目標檢測中的算法設計范式&#xff08;1&#xff09;one-stage&#xff08;2&am…

【軟件設計師:軟件】20.軟件設計概述

一、軟件設計基本原則 一、軟件設計基本原則 1. 模塊 是指執行某一特定任務的數據結構和程序代碼。 將模塊的接口和功能定義為其外部特性將模塊的局部數據和實現該模塊的程序代碼稱為內部特性。在模塊設計時,最重要的原則就是實現信息隱蔽和模塊獨立。 2 . 信息隱蔽 將每…

軟件工程之面向對象分析深度解析

前文基礎&#xff1a; 1.軟件工程學概述&#xff1a;軟件工程學概述-CSDN博客 2.軟件過程深度解析&#xff1a;軟件過程深度解析-CSDN博客 3.軟件工程之需求分析涉及的圖與工具&#xff1a;軟件工程之需求分析涉及的圖與工具-CSDN博客 4.軟件工程之形式化說明技術深度解…

需求分析階段測試工程師主要做哪些事情

在軟件測試需求分析階段&#xff0c;主要圍繞確定測試范圍、明確測試目標、細化測試內容等方面開展工作&#xff0c;為后續測試計劃的制定、測試用例的設計以及測試執行提供清晰、準確的依據。以下是該階段具體要做的事情&#xff1a; 1. 需求收集與整理 收集需求文檔&#x…

vLLM部署Qwen2-7B模型推理

vllm簡介 vLLM是一個高效的大語言模型推理和部署服務系統&#xff0c;專為大型語言模型的高效執行而設計。它不僅支持多種量化技術以減少模型大小和加速推理過程&#xff0c;還提供了與OpenAI API兼容的服務接口&#xff0c;使得現有的應用程序能夠無縫對接。 一、前提環境 …

【STM32 學習筆記】GPIO輸入與輸出

GPIO詳解 一、GPIO基本概念 GPIO&#xff08;通用輸入輸出&#xff09;是微控制器與外部設備交互的核心接口&#xff0c;具有以下特性&#xff1a; 可編程控制輸入/輸出模式支持數字信號的讀取與輸出集成多種保護機制復用功能支持片上外設連接 二、GPIO位結構解析 2.1 保護二…

安科瑞光伏綜自系統在新能源電站中的應用及調度上傳方案研究

摘要 隨著全球對清潔能源需求的不斷增長&#xff0c;光伏發電作為一種可持續的能源解決方案&#xff0c;正迅速發展。光伏綜合自動化系統&#xff08;綜自系統&#xff09;在確保光伏電站高效、穩定運行方面起著關鍵作用。本文詳細介紹了安科瑞光伏綜自系統&#xff0c;包括其背…

[python] 函數2-匿名函數

一 匿名函數 格式: 函數名 lambda 形參 : 返回值(表達式) 調用: 結果 函數名(實參) 一般只有一行代碼,他是對def定義函數的一種簡化,只能實現簡單的邏輯 邏輯復雜時不要使用lambda add lambda a,b: ab # a,b就是形參 print(add(2,5)) 1.1 無參數 noargs_func lambda…

深入理解C/C++內存管理:從基礎到高級優化實踐

一、內存區域劃分與基礎管理機制?? ??棧&#xff08;Stack&#xff09;?? 棧由系統自動管理&#xff0c;用于存儲函數調用時的局部變量、參數及返回地址。其特點是高效但空間有限&#xff08;通常1-8MB&#xff09;&#xff0c;遵循后進先出&#xff08;LIFO&#xff09;…

kafka 面試總結

Kafka的冪等性是一種機制&#xff0c;確保生產者發送的每條消息在Broker端只被持久化一次&#xff0c;即使生產者因網絡問題等原因重試發送&#xff0c;也不會導致消息重復。 實現原理 生產者ID&#xff08;PID&#xff09; 每個生產者實例在初始化時&#xff0c;會被分配一個…

uniapp|實現多終端聊天對話組件、表情選擇、消息發送

基于UniApp框架,實現跨平臺多終端適配的聊天對話組件開發、表情選擇交互設計及消息發送,支持文本與表情混合渲染。 目錄 聊天界面靜態組件實現消息列表布局消息氣泡雙向布局輔助元素定位與樣式靜態數據模擬與擴展性設計表情選擇器靜態模塊浮層實現符號網格排列多端樣式適配方…

LabVIEW超聲波液位計檢定

在工業生產、運輸和存儲等環節&#xff0c;液位計的應用十分廣泛&#xff0c;其中超聲波液位計作為非接觸式液位測量設備備受青睞。然而&#xff0c;傳統立式水槽式液位計檢定裝置存在受建筑高度影響、量程范圍受限、流程耗時長等問題&#xff0c;無法滿足大量程超聲波液位計的…

C++漫步結構與平衡的殿堂:AVL樹

文章目錄 1.AVL樹的概念2.AVL樹的結構3.AVL樹的插入4.AVL樹的旋轉4.1 左單旋4.2 右單旋4.3 右左雙旋4.4 左右雙旋 5.AVL樹的刪除6.AVL樹的高度7.AVL樹的平衡判斷希望讀者們多多三連支持小編會繼續更新你們的鼓勵就是我前進的動力&#xff01; 二叉搜索樹有其自身的缺陷&#xf…

Verilog Test Fixture 時鐘激勵

1、占空比50%時鐘產生 always begin<clock> 1b0 ;#<PERIOD/2> ;<clock> 1b1 ;#<PERIOD/2> ; end reg <clock> 1b0 ;alwaysbegin#<PERIOD/2> ;<clock> ~<clock> ;end 2…