iT邦幫忙

2022 iThome 鐵人賽

DAY 3
2
自我挑戰組

三十天,PG與我系列 第 3

PostgreSQL特性介紹-MVCC

  • 分享至 

  • xImage
  •  

前言

在SQL資料庫裏面,有transaction的機制來確保資料的完整性。PostgreSQL也有支援此類功能,可以讓使用者把多個SQL command包在同一個transaction裡面成為一個原子單位,這樣可以確保整個transaction裡面的指令要不都有確實執行,要不就是執行失敗然後回復到原先的狀態。
完善的Transaction機制可以讓資料庫具有ACID的特性,這四個英文字母分別代表
Atomicity(transaction必須要以一個單位執行完畢)
Consistency(transaction在執行前後資料都必須是正確的狀態)
Isolation(transaction在執行中不會被其他transaction干擾)以及
Durability(系統崩潰時,如果有沒做完的transaction變更被套用,必須要有相關措施來維持資料完整性)

Transaction的使用

(首先輸入)
BEGIN;

(中間放各種SQL...)

(想要的指令都輸入完之後,如果要將transaction所做的資料變更套用到資料庫就輸入)
COMMIT;
(或者如果想反悔撤銷這個transaction)
ROLLBACK;

Transaction Isolation

在支援多人連線同時操作的資料庫系統裡,許多的使用者可以同時開啟並操作不同的transaction,這時使用者在操作過程中對資料的變更,要如何反映在其他使用者作查詢的時候就是一個值得討論的問題。在SQL standard定義了幾種不同的isolation level,來定義資料在不同transaction之間的可見性。

Anomalies in SQL standard

  • Dirty read:一個transaction可以讀到其他transaction尚未commit的變更
  • Non-repeatable read:在一個transaction兩次讀取同一行中間,有其他transaction變更該行的內容且commit,使得兩次讀出的結果不一致
  • Phantom read:一個transaction多次查詢符合條件的表格行,中間有其他transaction修改了表格的內容且commit,導致兩次查詢的結果不一致
    https://ithelp.ithome.com.tw/upload/images/20220903/20114934lDQkSN58I5.png
    (來源:https://postgrespro.com/blog/pgsql/5967856)

PostgreSQL提供使用者選擇Read uncommitted/Read committed/Repeatable read以及Serializable這幾種isolation level,各個isolation level的規範可以參考上面的資料。越後面的選項可以避免掉越多的Anomaly,但是對效能影響也越大。Postgres預設的isolation level是Read committed。

Postgres如何做資料的可見性判斷?

PostgreSQL利用MVCC的方式,對於表格的每一行都有xmin及xmax的隱藏欄位,分別記錄該行被建立及刪除的transaction ID。當表格行被刪除或更新的時候,原本的資料會被保留在系統內,其上xmax欄位的資訊會從原本的0被更新為執行更新/刪除動作的transaction ID。
Postgres在transaction啟動的時候會建立一份snapshot,裡面紀錄xmin(snapshot被建立時最早的活躍transaction ID)/xmax(snapshot被建立之後的下一個transaction ID)以及xip list(transactions in progress, snapshot建立時仍在作動尚未commit的交易)。
Postgres會用這些資訊搭配一系列的規則來判斷資料的可見性,簡單的說就是在snapshot.xmin之前做的變更都是可以被當前transaction給看到,在snapshot.xmax之後所做的變更一定是看不到,而如果是在xip list裡面,則進一步查詢該xid的transaction狀態來做判斷。

VACUUM

由於Postgres使用MVCC管理多個資料版本的運作模式,資料庫在不斷的UPDATE/DELETE之後,在磁碟上的大小會越來越大。另外transaction ID是有大小限制的(32個bit, 2的32次方),transaction ID在不斷遞增之後總會有用完額度、需要從零開始的時候,到時候要透過ID來比較transaction的先後順序可能就會有些問題。
透過執行VACUUM這個維護性的操作,可以掃描table裡面已經不需要被使用的tuple(對資料行的稱呼),釋放其空間讓之後做插入的tuple可以使用,表格占用的磁碟空間就不會繼續變大。另外VACUMM FREEZE也可以在執行時將小於當前transaction ID的tuple給設定為frozen,代表之後所有的transaction都可以看到該tuple。
PostgreSQL有AUTOVACUMM的功能,可以自動在一定時間過後執行VACUUM,相關的參數有以下三個
vacuum_freeze_min_age:當前XID超過tuple的xmin大於此參數時,VACUUM會將此tuple給凍結
vacuum_freeze_table_age:當前XID超過table的xmin大於此參數時,會掃描table所有的page來進行凍結
autovacuum_freeze_max_age:當前XID超過tuple的xmin大於此參數時,強制執行凍結


上一篇
Postgre 使用者與權限管理
下一篇
PostgreSQL物理檔案架構
系列文
三十天,PG與我30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言