PostgreSQL 的 pg_advisory_lock_shared 函數

PostgreSQL 的 pg_advisory_lock_shared 函數詳解

pg_advisory_lock_shared 是 PostgreSQL 提供的共享咨詢鎖函數,允許多個會話同時獲取相同鍵值的共享鎖,但排斥排他鎖。

共享咨詢鎖 vs 排他咨詢鎖

鎖類型共享鎖 (pg_advisory_lock_shared)排他鎖 (pg_advisory_lock)
并發性允許多個會話同時持有同一時間只能由一個會話持有
排斥性排斥排他鎖排斥共享鎖和排他鎖
使用場景讀多寫少場景獨占訪問場景

共享咨詢鎖函數家族

PostgreSQL 提供以下共享咨詢鎖相關函數:

函數描述鎖類型
pg_advisory_lock_shared(key)獲取共享會話級咨詢鎖(阻塞)共享鎖
pg_try_advisory_lock_shared(key)嘗試獲取共享會話級咨詢鎖(非阻塞)共享鎖
pg_advisory_xact_lock_shared(key)獲取共享事務級咨詢鎖(阻塞)共享鎖
pg_try_advisory_xact_lock_shared(key)嘗試獲取共享事務級咨詢鎖(非阻塞)共享鎖
pg_advisory_unlock_shared(key)釋放共享會話級咨詢鎖-

函數詳解

1 pg_advisory _lock_shared(key bigint)

功能:獲取會話級共享咨詢鎖(阻塞)

參數

  • key :64位整數鎖標識

示例

-- 會話1獲取共享鎖
SELECT pg_advisory_lock_shared(123456);-- 會話2可以同時獲取相同的共享鎖
SELECT pg_advisory_lock_shared(123456);-- 但會話3嘗試獲取排他鎖會被阻塞
SELECT pg_advisory_lock(123456); -- 阻塞直到共享鎖釋放

2 pg_try_advisory_lock_shared(key bigint)

功能:嘗試獲取共享會話級咨詢鎖(非阻塞)

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

示例

DO $$
BEGINIF pg_try_advisory_lock_shared(123456) THENRAISE NOTICE 'Shared lock acquired, performing read operations...';-- 執行只讀操作PERFORM pg_advisory_unlock_shared(123456);ELSERAISE NOTICE 'Could not acquire shared lock';END IF;
END $$;

3 pg_advisory_xact_lock_shared(key bigint)

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

示例

BEGIN;
SELECT pg_advisory_xact_lock_shared(123456);
-- 執行只讀操作
COMMIT; -- 鎖自動釋放

鎖兼容性矩陣

當前持有鎖 \ 請求鎖共享鎖排他鎖
無鎖允許允許
共享鎖允許阻塞
排他鎖阻塞阻塞

實際應用場景

場景1:讀寫分離控制

-- 讀操作使用共享鎖
DO $$
BEGINPERFORM pg_advisory_lock_shared(555);-- 多個會話可以同時執行讀操作RAISE NOTICE 'Reading data: %', (SELECT count(*) FROM large_table);PERFORM pg_advisory_unlock_shared(555);
EXCEPTION WHEN OTHERS THENPERFORM pg_advisory_unlock_shared(555);RAISE;
END $$;-- 寫操作使用排他鎖
DO $$
BEGINPERFORM pg_advisory_lock(555); -- 會阻塞直到所有共享鎖釋放-- 獨占執行寫操作INSERT INTO large_table VALUES (...);PERFORM pg_advisory_unlock(555);
EXCEPTION WHEN OTHERS THENPERFORM pg_advisory_unlock(555);RAISE;
END $$;

場景2:緩存更新控制

-- 緩存讀取(多個客戶端可同時讀取)
CREATE OR REPLACE FUNCTION get_cached_data(cache_key text) RETURNS json AS $$
DECLAREresult json;
BEGIN-- 獲取共享鎖(允許并發讀取)PERFORM pg_advisory_lock_shared(hashtext(cache_key));SELECT data INTO result FROM cache_table WHERE key = cache_key;PERFORM pg_advisory_unlock_shared(hashtext(cache_key));RETURN result;
END;
$$ LANGUAGE plpgsql;-- 緩存更新(獨占訪問)
CREATE OR REPLACE FUNCTION update_cache(cache_key text, new_data json) RETURNS void AS $$
BEGIN-- 獲取排他鎖(阻塞直到所有共享鎖釋放)PERFORM pg_advisory_lock(hashtext(cache_key));-- 執行更新INSERT INTO cache_table(key, data, updated_at)VALUES (cache_key, new_data, NOW())ON CONFLICT (key) DO UPDATESET data = EXCLUDED.data, updated_at = NOW();PERFORM pg_advisory_unlock(hashtext(cache_key));
END;
$$ LANGUAGE plpgsql;

場景3:配置熱加載

-- 配置讀取(多個服務實例可同時讀取)
CREATE OR REPLACE FUNCTION get_config() RETURNS SETOF config_entry AS $$
BEGIN-- 獲取共享鎖確保配置加載過程中不被修改PERFORM pg_advisory_lock_shared(1); -- 使用固定鍵值1表示配置鎖RETURN QUERY SELECT * FROM application_config;PERFORM pg_advisory_unlock_shared(1);
END;
$$ LANGUAGE plpgsql;-- 配置更新(管理員調用)
CREATE OR REPLACE FUNCTION reload_config(new_config json) RETURNS void AS $$
BEGIN-- 獲取排他鎖確保沒有服務正在讀取配置PERFORM pg_advisory_lock(1);-- 清空并重新加載配置TRUNCATE application_config;INSERT INTO application_configSELECT * FROM json_populate_recordset(NULL::config_entry, new_config);PERFORM pg_advisory_unlock(1);
END;
$$ LANGUAGE plpgsql;

監控共享咨詢鎖

查看當前共享鎖

SELECT pid, locktype, mode, granted 
FROM pg_locks 
WHERE locktype = 'advisory' AND mode LIKE '%Share%';

查看鎖等待情況

SELECT blocked.pid AS blocked_pid,blocking.pid AS blocking_pid,blocked.query AS blocked_query,blocking.query AS blocking_query,blocked.mode AS blocked_mode,blocking.mode AS blocking_mode
FROM pg_catalog.pg_locks blocked
JOIN pg_catalog.pg_stat_activity blocking ON blocking.pid = blocked.blocking_pid
WHERE blocked.locktype = 'advisory' AND NOT blocked.granted;

注意事項

  1. 鎖釋放

    • 必須確保每個 pg_advisory_lock_shared() 調用都有對應的 pg_advisory_unlock_shared()
    • 事務級共享鎖會在事務結束時自動釋放
  2. 死鎖風險

    • 共享鎖之間不會死鎖
    • 但共享鎖與排他鎖混合使用時可能產生死鎖
    • 建議使用固定的鎖獲取順序
  3. 性能考慮

    • 共享鎖比排他鎖允許更高的并發性
    • 但大量共享鎖仍可能影響性能
  4. 鎖粒度

    • 使用不同鍵值控制不同資源的訪問
    • 避免使用太少鍵值導致過度爭用
  5. 會話管理

    • 確保異常情況下鎖能被釋放(使用EXCEPTION塊)
    • 長時間持有鎖可能導致其他會話長時間等待

pg_advisory_lock_shared 是實現讀多寫少場景并發控制的強大工具,合理使用可以顯著提高系統吞吐量,特別是在需要協調多個讀取者與少量寫入者的場景中。

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

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

相關文章

Halcon之計算抓取螺母的位姿

文章目錄 1,項目說明。2,注意事項3,關聯的主要算子3.1, gen_parallels_xld 3.2 ,convert_pose_type 4,程序流程。5,代碼6,Demo鏈接。 1,項目說明。 Robot標定使用的模式…

互聯網大廠Java求職面試:AI集成場景下的技術挑戰與架構設計

標題:互聯網大廠Java求職面試:AI集成場景下的技術挑戰與架構設計 第一幕:向量數據庫選型與性能調優 技術總監(嚴肅臉): 鄭薪苦,我們最近在做一個基于大語言模型的企業級AI應用,需要…

ABB電機控制和保護單元與Profibus DP主站轉Modbus TCP網關快速通訊案例

ABB電機控制和保護單元與Profibus DP主站轉Modbus TCP網關快速通訊案例 在現代工業自動化系統中,設備之間的互聯互通至關重要。Profibus DP和Modbus TCP是兩種常見的通信協議,分別應用于不同的場景。為了實現這兩種協議的相互轉換,Profibus …

智慧農業、智慧養殖平臺—監控攝像頭管理監控設計—仙盟創夢IDE

智慧養殖 監控攝像頭是核心管理工具,主要通過以下方式提升養殖效率與管理水平: 環境實時監測:對養殖區域進行全天候可視化監控,及時捕捉溫度、濕度、通風等環境要素變化,確保動物生存環境穩定 。例如在規模化豬場&…

YOLO 從入門到精通學習指南

一、引言 在計算機視覺領域,目標檢測是一項至關重要的任務,其應用場景廣泛,涵蓋安防監控、自動駕駛、智能交通等眾多領域。YOLO(You Only Look Once)作為目標檢測領域的經典算法系列,以其高效、快速的特點受到了廣泛的關注和應用。本學習指南將帶領你從 YOLO 的基礎概念…

Java 24新特性深度解析:從優化技巧到高手進階指南

一、Java 24核心新特性詳解 Java 24作為長期支持版本(LTS),帶來了許多令人振奮的新特性,下面我們將深入探討其中最值得關注的改進。 1. 字符串模板(String Templates)正式發布 字符串模板結束了Java字符串拼接的混亂時代&#…

《類和對象(中)》

引言: 上次我們主要學習了類的相關知識,今天我們就來學習類和對象(中),今天也會用到之前學習過的東西,可以說是前面知識的結合,較前面會難一點(打個預防針)。 一:類的默認成員函數…

為什么 AI 理解不了邏輯問題?

人類擅長“如果 A 則 B”,AI 擅長“這個像那個”。邏輯推理?對它來說是一場災難性的認知挑戰。 前言 在實際使用 AI(尤其是大型語言模型,比如 GPT、Claude、Gemini 等)時,我們常發現一個詭異的現象:它們文采斐然,甚至能講出笑話,但一旦問點小學奧數或邏輯問題,就集體…

C# 使用SunnyUI控件 (VS 2019)

前言:建議下載源碼,源碼中包含了各種控件的用法案例。 下載 幫助文檔: 文檔預覽 - Gitee.comGitee: SunnyUI: SunnyUI.NET 是基于.NET Framework 4.0、.NET8、.NET9 框架的 C# WinForm UI、開源控件庫、工具類庫、擴展類庫、多頁面開發框架。GitHub: h…

Spring Cloud: Nacos

Nacos Nacos是阿里巴巴開源的一個服務發現,配置管理和服務管理平臺。只要用于分布式系統中的微服務注冊,發現和配置管理,nacos是一個注冊中心的組件 官方倉庫:https://nacos.io/ Nacos的下載 Releases alibaba/nacos 在官網中…

Linux下的c/c++開發之操作mysql數據庫

libmysqlclient-dev介紹(Linux 下的 Mysql C/C 開發包) libmysqlclient-dev 是一個開發包,在Linux環境下為使用 MySQL C API 進行開發的c/c程序員提供頭文件(如 mysql.h)和靜態庫/動態庫的鏈接信息(如 lib…

Java EE(Spring+Spring MVC+MyBatis)從入門到精通企業級應用開發教程——1初識MyBatis框架

1、MyBatis工作原理 MyBatis操作數據庫流程分為8個步驟,具體介紹如下: (1)MyBatis讀取核心配置文件mybatis-config.xml mybatis-config.xml核心配置文件主要配置了MyBatis的運行環境等信息。 (2)加載映射…

【許可證】Open Source Licenses

長期更新 擴展:shield.io裝飾 開源許可證(Open Source Licenses)有很多種,每種都有不同的授權和限制,適用于不同目的。 默認的ISC🟰MIT License是否可商用是否要求開源衍生項目是否必須署名是否有專利授權…

ZooKeeper工作機制與應用場景

目錄 1.1、概述1.2、選舉機制1.2.1、選舉觸發條件1.2.2、選舉規則1.2.3、選舉過程詳解 1.3、數據同步機制1.3.1、正常同步1.3.2、宕機同步 1.4、客戶端常用命令1.5、應用場景1.5.1、配置管理1.5.2、命令服務1.5.3、分布式鎖服務1.5.4、集群管理1.5.5、分布式ID1.5.6、分布式協調…

前端面經-VUE3篇(四)--pinia篇-基本使用、store、state、getter、action、插件

一、基本使用 1、什么是 Pinia? Pinia 是 Vue.js 的官方狀態管理庫,是 Vuex 的“升級版”。它專為 Vue 3 和 Composition API 設計,用于管理多個組件之間共享的數據(也叫“全局狀態”)。 2、為什么需要狀態管理庫&a…

數據結構之圖的遍歷

圖的遍歷 圖的遍歷目的是訪問圖的每一個頂點恰好一次,,同時訪問圖中每條邊恰好一 次。 對于無向圖,常見的遍歷方式有深度優先遍歷(Depth-First Search, DFS) 和廣度優先遍歷(Breadth-First Search, BFS)。…

Ubuntu 第11章 網絡管理_常用的網絡配置命令

為了管理網絡,Linux提供了許多非常有用的網絡管理命令。利用這些命令,一方面可以有效地管理網絡,另一方面出現網絡故障時,可以快速進行診斷。本節將對Ubuntu提供的網絡管理命令進行介紹。 11.2.1 ifconfig命令 關于ifconfig命令&…

Qt解決自定義窗口樣式不生效問題

方法一: this->setAttribute(Qt::WA_StyledBackground, true); 方法二: 將類繼承QWidget 改成繼承 QFrame class MyWidget : public QFrame {} 方法三:重新實現QWidget的paintEvent函數時,使用QStylePainter繪制。 void p…

HNUST湖南科技大學-軟件測試期中復習考點(保命版)

使用說明:本復習考點僅用于及格保命。軟件測試和其他專業課不太一樣,記憶的太多了,只能說考試的時候,想到啥就寫啥,多寫一點!多寫一點!多寫一點!(重要事情說三遍&#xf…

ES6 知識點整理

一、變量聲明:var、let、const 的區別 作用域 var:函數作用域(函數內有效)。let/const:塊級作用域({} 內有效,如 if、for)。 變量提升 var 會提升變量到作用域頂部(值為…