PG資料庫的鎖咋弄得這麼複雜呢
談到鎖,很多朋友和我抱怨過PG的鎖的對外展現太過於複雜,很多初學者根本搞不懂,不像其他資料庫行鎖、表鎖,一目瞭然。Postgresql資料庫是一種十分學院派的資料庫,因為從本質上講,PG是一種物件-關係型資料庫,所以PG資料庫的底層完全按照物件資料庫來設計。為了貫徹物件特性,PG鎖的基礎是物件鎖,所以從DBA的角度來看,就很複雜了。
如果你是一個Oracle DBA,那麼你可能習慣於看dba_locks這樣的檢視,Oracle的鎖劃分的很細,有上百種鎖,不過Oracle的鎖機制的底層是統一的,都是Enqueue,所以從監控檢視上,Oracle的所有鎖都是統一的。Oracle的鎖使用型別(TYPE),持有模式(MODE_HELD),申請模式(MOD_REQUESTED),引數1(LOCK_ID1),引數2(LOCK_ID2)等幾個有限的欄位統一表示所有的鎖型別。
從DBA_LOCKS檢視的結構上可以看出,Oracle把繁瑣的鎖用一個十分簡單的資料結構來描述了。
相對而言,PG的pg_locks檢視就要複雜的多,我們來看pg_locks這個PG用來展現鎖情況的檢視:
除了locktype和Oracle類似外,其他的欄位都讓人感到有些複雜。實際上這個和PG資料庫的物件資料庫的特性是有關係的。如果從物件層面來看,需要進行序列化處理的物件層次十分複雜,正是因為PG鎖考慮了物件級的多個層面的東西,把所有的需要序列化的需求都歸納到有限的幾類鎖中(相對於Oracle鎖的種類有上百種),因此要想把PG的鎖完全統一起來並不容易。
我以前對PG鎖的理解也比較膚淺,因為在絕大多數系統中,我們只需要關注事務鎖就可以了。不過PG的事務鎖也不那麼直觀,可能我們在pg_locks中會看到一些讓人感到十分困惑的資料。
從我們現在的一個純粹交易型的測試環境中,我們看到鎖的型別有5種。
這些鎖到底是什麼含義呢?到底哪個才是行鎖呢?是tuple嗎?直到我認真的閱讀了俄羅斯postgrepro公司的PG大師葉格爾-羅格夫關於PG鎖的系列文章,才算從根兒上理解了PG的鎖。從此再看到亂七八糟的PG鎖就變得十分舒服和親切了。從今天開始,我分幾期把從葉格爾大師那裡學到的知識給大家分享一下。
PG的物件級鎖有很多種,上面是葉格爾文章中的截圖,列出了PG中常見的物件級鎖。對於鎖的型別,不同的PG版本可能鎖的種類略有不同。從等待事件中我們可以看到一些種類的鎖產生的等待事件:
從廣義上講,PG把實現序列化的互斥機制都稱為鎖,所以PG鎖實際上融合了Oracle資料庫的ENQUEUE/LATCH/MUTEX等機制,所以相當複雜。當然大多數序列化共享記憶體操作的PG鎖都使用了類似LATCH的LWLOCK,不過二者之間並不是完全等同的。要觀察這些鎖的情況,我們都可以通過pg_locks這個檢視。因為不同的鎖的實現方式都會不同,不同型別的鎖的引數也不相同,所以pg_locks中的欄位很多。有時候甚至會引起我們對行鎖的分析都出現困難。關於行鎖的詳細分析今天因為篇幅問題,可能沒有時間展開了,我會在後續的系列文章中一點點的展開討論。以前在Percona上看到過一篇文章,裡面有一個解析pg_locks的SQL語句。
SELECT pid, virtualtransaction AS vxid, locktype AS lock_type,mode AS lock_mode, granted,
CASE
WHEN virtualxid IS NOT NULL AND transactionid IS NOT NULL THEN virtualxid || ' ' || transactionid
WHEN virtualxid::text IS NOT NULL
THEN virtualxid
ELSE
transactionid::text
END AS xid_lock, relname,
page, tuple, classid, objid, objsubid
FROM pg_locks LEFT OUTER JOIN pg_class ON (pg_locks.relation = pg_class.oid)
WHERE pid != pg_backend_pid();
用這條語句來解析PG_LOCKS後,我們看這些鎖資料就舒服多了。下面來看一個例子:
關於virtualxid和TransactionID的區別我們明天的文章中再來分析,不同的鎖的型別其引數是不同的。relation鎖的是relations物件級別上的鎖,用於保證某個relation在被訪問時不被改變或者刪除,而PG的事務鎖(比如transactionid鎖 )都是針對事務的。
如果你以前是Oracle DBA那麼理解PG鎖的障礙來自於PG鎖的型別劃分與Oracle在維度上的不同。Oracle是按照功能來劃分鎖的,比如行鎖(TX)、表鎖(TM)、表空間鎖(TT)、SEQUENCE鎖(SQ)。而PG的鎖是按照物件的粒度來劃分的,把相同級別的不同物件劃分為同類。除了行鎖(transactionid)之外,其他鎖的處理模式都是類似的,因為行鎖的併發量巨大,因此針對行鎖採用了獨特的處理方式,以避免效能問題。
正是因為PG的鎖十分複雜,因此今天我們重點來討論關係型鎖這種和運維與應用開發關係最為密切的鎖。要了解關係級鎖的細節,一定要首先了解鎖的模式,PG的關係級鎖有著相當複雜的鎖模式,下面這個表格可以讓我們快速理解複雜的鎖模式。
Access Share是最弱級別的鎖,這種鎖是由select操作產生的,而Access Exclusive是最嚴格的鎖,如果在關係上執行DROP/TRUNCATE等操作,會產生這種鎖。我們如何來理解這張表呢?用一個最為簡單的CREATE INDEX來做個示範吧。我們看到CREATE INDEX會持有SHARE模式的鎖,這個模式相容Access Share、Row Share和SHARE,因此多個CREATE INDEX可以併發執行,同時SELECT和SELECT FOR UPDATE操作可以不受阻塞執行。而INSERT/DELETE/UPDATE操作需要Row Exclusive模式的鎖,會受到阻止。
今天因為時間關係,就先講到這裡吧,看到這裡的朋友可能現在還是有點懵圈,不知道老白到底想要講什麼。我想把這個系列全部看完之後,一切都會明瞭的。明天南瑞要搞兩年一度的子衿IT基礎架構大會,我一大早要去參會,如果今天下午有時間,我會把第二部分寫出來,明早發出。看完第二部分,大家就會明白我今天為什麼要寫這一篇了。
- 技術分享 | orchestrator--運維--配置叢集自動切換&測試
- AIOPS的莫拉維克悖論
- 詳談 MySQL 8.0 原子 DDL 原理
- 為什麼不建議用 from xxx import *
- 最近解決的兩個拖延數年的問題
- Oracle資料庫解決方案集錦
- 新一代雲原生資料庫暢想
- MySQL8.0賬戶system_user許可權,你瞭解嗎?
- Data Fabric,下一個風口?
- 帶著孩子做開學準備清單
- 十多年前的入職第一天
- 技術分享 | MySQL 編寫指令碼時避免煩人的警告
- GoldenGate案例一則:抽取程序無法捕獲資料
- 技術分享 | MySQL 設定管理員密碼無法生效一例
- PG資料庫的鎖咋弄得這麼複雜呢
- 金融業分散式資料庫選型及HTAP場景實踐
- 我們的企業為什麼寫不好文件
- 新資料庫時代,DBA 發展之路該如何選擇
- MySQL:修改系統時鐘會導致資料庫hang住嗎?
- 從程式設計師的盡頭是業務說起