PostgreSQL中MVCC 機制的實現(xiàn)
PostgreSQL 使用多版本并發(fā)控制(MVCC)作為其核心并發(fā)控制機制,這是它與許多其他數(shù)據(jù)庫系統(tǒng)的關(guān)鍵區(qū)別之一。MVCC 允許讀操作不阻塞寫操作,寫操作也不阻塞讀操作,從而提供高度并發(fā)性。
一 MVCC 基本原理
1.1 MVCC 核心概念
- 多版本:每行數(shù)據(jù)可以有多個版本同時存在
- 快照隔離:每個事務(wù)看到的是數(shù)據(jù)庫在某個時間點的"快照"
- 無讀鎖:讀操作不需要獲取鎖,不會阻塞寫操作
- 寫操作優(yōu)化:寫操作創(chuàng)建新版本而非直接修改現(xiàn)有數(shù)據(jù)
1.2 與傳統(tǒng)鎖機制對比
| 特性 | 傳統(tǒng)鎖機制 | MVCC |
|---|---|---|
| 讀-寫沖突 | 讀寫互相阻塞 | 讀寫不互相阻塞 |
| 并發(fā)度 | 較低 | 較高 |
| 實現(xiàn)復(fù)雜度 | 相對簡單 | 較復(fù)雜 |
| 存儲開銷 | 較小 | 較大(需要版本存儲) |
二 PostgreSQL MVCC 實現(xiàn)細(xì)節(jié)
2.1 系統(tǒng)列(System Columns)
PostgreSQL 每行數(shù)據(jù)都包含幾個隱藏的系統(tǒng)列:
SELECT xmin, xmax, cmin, cmax, ctid, * FROM your_table;
- xmin:創(chuàng)建該行版本的事務(wù)ID(插入事務(wù))
- xmax:刪除/鎖定該行版本的事務(wù)ID(初始為0)
- cmin/cmax:事務(wù)內(nèi)的命令標(biāo)識符
- ctid:行版本在表中的物理位置
2.2 事務(wù)狀態(tài)與可見性判斷
PostgreSQL 通過比較事務(wù)ID(xmin, xmax)和事務(wù)快照來判斷行版本是否可見:
- 如果 xmin 未提交或晚于當(dāng)前事務(wù)快照 → 不可見
- 如果 xmax 已提交且早于當(dāng)前事務(wù)快照 → 不可見(已刪除)
- 否則可見
2.3 事務(wù)ID管理
- 事務(wù)ID是32位整數(shù),約40億個可能值
- PostgreSQL 使用事務(wù)ID環(huán)繞保護機制
- 通過
vacuum過程凍結(jié)舊的事務(wù)ID
三 MVCC 具體行為示例
3.1 插入操作
-- 事務(wù)1 BEGIN; INSERT INTO test VALUES (1, 'data'); -- 此時xmin=當(dāng)前事務(wù)ID, xmax=0 COMMIT;
3.2 更新操作(實際是刪除+插入)
-- 事務(wù)2 BEGIN; UPDATE test SET value = 'new' WHERE id = 1; -- 原行xmax設(shè)置為事務(wù)2的ID -- 新行xmin=事務(wù)2的ID, xmax=0 COMMIT;
3.3 刪除操作
-- 事務(wù)3 BEGIN; DELETE FROM test WHERE id = 1; -- 行xmax設(shè)置為事務(wù)3的ID COMMIT;
四 MVCC 存儲實現(xiàn)
4.1 表文件結(jié)構(gòu)
- 主數(shù)據(jù)文件(
oid)存儲當(dāng)前行版本 - 每個行版本都包含xmin/xmax等系統(tǒng)字段
- 更新操作不會原地修改,而是創(chuàng)建新版本
4.2 事務(wù)快照
-- 查看當(dāng)前事務(wù)快照 SELECT pg_current_snapshot(); -- 輸出示例: 100:100: -- 格式為 xmin:xmax:xip_list
4.3 可見性映射(Visibility Map)
- 標(biāo)記哪些數(shù)據(jù)塊只包含對所有事務(wù)可見的元組
- 加速vacuum過程
五 MVCC 維護機制
5.1 VACUUM 機制
-- 常規(guī)vacuum(不鎖表) VACUUM [VERBOSE] [ANALYZE] table_name; -- 全量vacuum(需要鎖) VACUUM FULL [VERBOSE] table_name;
VACUUM作用:
- 回收死元組占用的空間
- 凍結(jié)舊的事務(wù)ID防止環(huán)繞
- 更新優(yōu)化器統(tǒng)計信息
- 更新可見性映射
5.2 自動vacuum
-- 查看自動vacuum設(shè)置 SELECT name, setting FROM pg_settings WHERE name LIKE 'autovacuum%'; -- 重要參數(shù) autovacuum = on -- 是否啟用 autovacuum_vacuum_threshold = 50 -- 觸發(fā)vacuum的更新/刪除元組閾值 autovacuum_analyze_threshold = 50 -- 觸發(fā)analyze的更新/刪除元組閾值 autovacuum_vacuum_scale_factor = 0.2-- 表大小的縮放因子
六 MVCC 優(yōu)缺點分析
優(yōu)勢
- 高并發(fā):讀寫不互相阻塞
- 讀一致性:事務(wù)看到一致的快照
- 避免鎖競爭:減少鎖等待時間
- 回滾高效:不需要專門的回滾段
劣勢
- 存儲開銷:需要保留多個版本
- 維護成本:需要定期vacuum
- 更新性能:更新實質(zhì)是刪除+插入
- 表膨脹:不當(dāng)維護會導(dǎo)致空間浪費
七 MVCC 優(yōu)化建議
7.1 合理配置autovacuum
-- 對大表調(diào)整autovacuum參數(shù) ALTER TABLE large_table SET ( autovacuum_vacuum_scale_factor = 0.05, autovacuum_vacuum_threshold = 10000 );
7.2 監(jiān)控表膨脹
-- 查看表膨脹情況 SELECT schemaname, relname, pg_size_pretty(pg_relation_size(relid)) as size, n_dead_tup, n_live_tup FROM pg_stat_user_tables ORDER BY n_dead_tup DESC;
7.3 定期維護
-- 對大表定期手動vacuum VACUUM (VERBOSE, ANALYZE) large_table; -- 在低峰期執(zhí)行vacuum full VACUUM FULL VERBOSE table_name;
7.4 事務(wù)設(shè)計優(yōu)化
- 避免長時間運行的事務(wù)
- 將大事務(wù)拆分為小事務(wù)
- 避免在事務(wù)中執(zhí)行不必要的查詢
到此這篇關(guān)于PostgreSQL中MVCC 機制的實現(xiàn)的文章就介紹到這了,更多相關(guān)PostgreSQL MVCC機制 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
postgresql 實現(xiàn)字符串分割字段轉(zhuǎn)列表查詢
這篇文章主要介紹了postgresql 實現(xiàn)字符串分割字段轉(zhuǎn)列表查詢,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02
解決postgreSql 將Varchar類型字段修改為Int類型報錯的問題
這篇文章主要介紹了解決postgreSql 將Varchar類型字段修改為Int類型報錯的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
PostgreSQL教程(七):函數(shù)和操作符詳解(3)
這篇文章主要介紹了PostgreSQL教程(七):函數(shù)和操作符詳解(3),本文講解了序列操作函數(shù)、條件表達(dá)式、數(shù)組函數(shù)和操作符、系統(tǒng)信息函數(shù)、系統(tǒng)管理函數(shù)等內(nèi)容,需要的朋友可以參考下2015-05-05
postgresql高級應(yīng)用之行轉(zhuǎn)列&匯總求和的實現(xiàn)思路
這篇文章主要介紹了postgresql高級應(yīng)用之行轉(zhuǎn)列&匯總求和的實現(xiàn)思路,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-05-05
postgresql 實現(xiàn)查詢某時間區(qū)間的所有日期案例
這篇文章主要介紹了postgresql 實現(xiàn)查詢某時間區(qū)間的所有日期案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01
基于PostgreSQL和mysql數(shù)據(jù)類型對比兼容
這篇文章主要介紹了基于PostgreSQL和mysql數(shù)據(jù)類型對比兼容,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
PostgreSQL數(shù)據(jù)庫授權(quán)與自增序列操作實例代碼
在PostgreSQL中,自增序列是一種特殊的數(shù)據(jù)庫對象,用于生成唯一的數(shù)字序列,通常用于主鍵值的自動生成,這篇文章主要介紹了PostgreSQL數(shù)據(jù)庫授權(quán)與自增序列操作的相關(guān)資料,需要的朋友可以參考下2025-08-08

