在SQL資料庫裏面,有transaction的機制來確保資料的完整性。PostgreSQL也有支援此類功能,可以讓使用者把多個SQL command包在同一個transaction裡面成為一個原子單位,這樣可以確保整個transaction裡面的指令要不都有確實執行,要不就是執行失敗然後回復到原先的狀態。
完善的Transaction機制可以讓資料庫具有ACID的特性,這四個英文字母分別代表
Atomicity(transaction必須要以一個單位執行完畢)
Consistency(transaction在執行前後資料都必須是正確的狀態)
Isolation(transaction在執行中不會被其他transaction干擾)以及
Durability(系統崩潰時,如果有沒做完的transaction變更被套用,必須要有相關措施來維持資料完整性)
(首先輸入)
BEGIN;
(中間放各種SQL...)
(想要的指令都輸入完之後,如果要將transaction所做的資料變更套用到資料庫就輸入)
COMMIT;
(或者如果想反悔撤銷這個transaction)
ROLLBACK;
在支援多人連線同時操作的資料庫系統裡,許多的使用者可以同時開啟並操作不同的transaction,這時使用者在操作過程中對資料的變更,要如何反映在其他使用者作查詢的時候就是一個值得討論的問題。在SQL standard定義了幾種不同的isolation level,來定義資料在不同transaction之間的可見性。
PostgreSQL提供使用者選擇Read uncommitted/Read committed/Repeatable read以及Serializable這幾種isolation level,各個isolation level的規範可以參考上面的資料。越後面的選項可以避免掉越多的Anomaly,但是對效能影響也越大。Postgres預設的isolation level是Read committed。
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狀態來做判斷。
由於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大於此參數時,強制執行凍結