Postgres併發處理
來源:小技術君
本文,我們將深入探討併發的概念以及Postgres中是如何處理它的。讓我們開始吧!
併發及其角色
電腦科學史上最受追捧的詞彙之一是併發[1]和並行[2]。如果沒有這兩者的需求,我們可以簡單地一次執行一個程式,不需要作業系統資源(RAM、CPU)在應用程式之間進行排程,從而使核心變得更簡單。核心的核心目的是排程和協調計算機資源和應用程式,使併發和並行成為可能。儘管沒有這些概念,整體複雜性可以減少95%,但顯然,95%的開發無法在沒有這些概念的情況下進行。
併發 vs 並行
併發是處理多個任務的能力,但不一定是同時執行它們。並行涉及同時執行多個任務,通常使用多個處理單元。雖然併發和並行被認為是*不同[3]*概念,但它們實質上宣揚相同的原則,即在給定的時間內處理多個操作。我們可以堅持使用“併發”這個詞。要具體解釋併發是如何在實現它的所有領域中處理的是不可能的,因為我們處理的所有計算機系統都是以併發作為基本概念構建的。但我們可以談論最主要的領域,即資料庫系統。每個資料庫系統都採用不同的策略實現併發,但最終,我們可以將其歸結為三種策略:
1.鎖[4] — 限制對特定資料或資源的訪問,確保只有一個使用者/程式/事務可以同時修改/檢視特定記錄或記錄集。2.多版本併發控制[5](MVCC) — 為每個使用者/程式/事務維護多個版本(下文更多介紹)。3.基於時間戳的協議[6] — 使用時間戳確定事務的序列化順序,確保事務以維護一致性的方式執行。
Postgres如何處理併發 ⛁
Postgres同時使用鎖和MVCC,但更傾向於其MVCC架構。
MVCC[7] 提供了事務之間的強大隔離[8]。這意味著每個事務都獲得其資料庫的快照或版本,其中包含有關已提交、進行中或尚未啟動的事務ID的資訊。
因此,每個快照包括:
•當前事務的事務ID。•活動事務ID列表 — 那些已經開始但尚未提交或回滾的事務。•在拍攝快照時提交的最高事務ID。在此之後的任何ID都被視為從快照的角度來看處於“未來”。
其目的是為每個事務建立一致的檢視,以避免讀寫之間的衝突。
MVCC事務內部流程
所有未提交的更改都在共享緩衝區快取和Write-Ahead Logging(WAL)系統中進行跟蹤,直到它們提交。一旦提交,這些更改就會被重新整理到資料庫中。為了更好地解釋MVCC的目的,考慮兩個併發事務:一個更新了行的列,另一個查詢了該行。如果第一個事務更新但尚未提交,而第二個在第一個提交之前進行查詢,可能會導致獲取未提交的更新行資料,這是不正確的,因為第一個事務有可能被中止。這種狀態稱為髒讀。Postgres如何解決這個問題呢?每個表都有帶有兩個系統列的行標頭:
•xmin — 建立行的事務ID。•xmax — 刪除行的事務ID。
由於MVCC快照具有事務ID(xmin)列表,因此每個事務都知道所有併發事務。在髒讀的情況下,第二個事務的快照中有第一個事務的ID在其併發事務列表中,因此Postgres會過濾該行並獲取所有其餘的符合條件的行。
有無MVCC的區別
更詳細地說,Postgres在執行時進行了多個檢查,以確定行是否對當前事務可見。僅當滿足以下xmin條件之一時,行才可見:
•xmin小於最高已提交事務ID。•它是當前事務的ID。
還應遵守以下xmax條件之一:
•xmax應為未設定狀態。•它引用一個截至事務快照時尚未提交或啟動的事務。
這些檢查在執行時進行,但目前尚不清楚它們是如何高效地進行的,以確保不影響效能。
使用MVCC模型而不是鎖的主要優勢在於,在MVCC中,用於寫入資料的鎖不會阻塞讀取資料,反之亦然。
Postgres MVCC不能處理的事情 💔
MVCC旨在防止併發的讀/寫衝突,但它不能處理併發的寫操作,這由傳統的鎖來管理。Postgres在不同層次(行、表)上提供了各種鎖定機制,但對於同一行的寫操作,它們應該按順序進行。
雖然MySQL也透過其預設儲存引擎InnoDB提供MVCC功能,但Postgres是首個將這一概念引入資料庫世界的。這種早期採用使Postgres在讀寫負載方面比MySQL更具效能優勢,因為MySQL沒有同等最佳化。然而,在讀重型系統中,MySQL更受歡迎,因為它已被證明比Postgres更為高效。
引用連結
[1]
併發: https://www.notion.so/How-concurrency-handled-in-postgres-0d9b873c9a6e45dabfbf5d21d1947c94?pvs=4[2]
並行: https://www.notion.so/How-concurrency-handled-in-postgres-0d9b873c9a6e45dabfbf5d21d1947c94?pvs=4[3]
不同: https://www.google.com/search?q=concurrency+vs+parallelism&sca_esv=599372071&sxsrf=ACQVn09k-k_w7TlIT8VC8wFgW6QmAVZdDw%3A1705555740621&ei=HLeoZfjKJeiRseMP5J-K8AY&ved=0ahUKEwj4yMGgmuaDAxXoSGwGHeSPAm4Q4dUDCBA&uact=5&oq=concurrency+vs+parallelism&gs_lp=Egxnd3Mtd2l6LXNlcnAiGmNvbmN1cnJlbmN5IHZzIHBhcmFsbGVsaXNtMhEQABiABBiKBRiRAhixAxiDATILEAAYgAQYigUYkQIyCxAAGIAEGIoFGJECMgsQABiABBiKBRiRAjIFEAAYgAQyBRAAGIAEMgUQABiABDIFEAAYgAQyBRAAGIAEMgUQABiABEi5CVCJBViRB3ACeAGQAQCYAXCgAdABqgEDMS4xuAEDyAEA-AEBwgIKEAAYRxjWBBiwA8ICDRAAGIAEGIoFGEMYsAPCAg0QABiABBgNGLEDGIMBwgIGEAAYBxgewgIHEAAYgAQYDeIDBBgAIEGIBgGQBgo&sclient=gws-wiz-serp[4]
鎖: https://blog.dbwatch.com/database-locks-how-to-monitor-and-manage-it[5]
多版本併發控制: [6]
基於時間戳的協議: ~:text=Timestamp%2Dbased%20protocols%20are%20concurrency,without%20the%20need%20for%20locking.[7]
MVCC: [8]
隔離:
來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70027826/viewspace-3006817/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL 併發處理MySql
- 處理併發衝突
- 併發問題處理方式
- 海量資料的併發處理
- 聊聊介面最大併發處理數
- 前端優化之高併發處理前端優化
- 併發處理規則最佳推薦
- Go併發呼叫的超時處理Go
- SQLite 併發的四種處理方式SQLite
- Spring如何處理執行緒併發Spring執行緒
- Entity Framework Core中的併發處理Framework
- Go 併發 2.2:錯誤處理模式Go模式
- ElasticSearch 文件併發處理以及文件路由Elasticsearch路由
- 使用Fan-Out模式併發處理模式
- 轉載:Java處理高併發量訪問的處理總結Java
- 處理高併發的一般思路
- 高併發實戰之冪等處理
- Apache Tomcat如何高併發處理請求ApacheTomcat
- Java併發---併發理論Java
- 高併發處理思路與手段(一):擴容
- 如何處理系統具有較大併發量?
- Python基礎之使用期物處理併發Python
- Python學習之路36-使用future處理併發Python
- 一次併發處理過程, 基於 RedisRedis
- ES 筆記三十七:處理併發讀寫操作筆記
- 如何提高伺服器的併發處理能力?硬核!伺服器
- 【TCP/IP】TCP伺服器併發處理&原始碼TCP伺服器原始碼
- Nginx實現高速併發處理的原理詳解Nginx
- 處理高併發 IO瓶頸解決紅包程式
- T-SQL:事務鎖下的併發處理(十五)SQL
- Python學習之路37-使用asyncio包處理併發Python
- node.js為什麼能處理高併發情景?Node.js
- MySQL原理簡介—8.MySQL併發事務處理MySql
- React setState合併和批量處理React
- 併發技術1:CSP併發理論
- 遠端觸發Jenkins的Pipeline任務的併發問題處理Jenkins
- JAVA多執行緒下高併發的處理經驗Java執行緒
- 3種方式實現python多執行緒併發處理Python執行緒