PostgreSQL數據庫xlog文件命名

我們會在postgresql數據庫的數據目錄下pg_xlog(新版本已經變爲pg_wal)目錄下看到下面這些文件:
在這裏插入圖片描述
如果第一次看到這些文件名可能覺得命名很奇怪,這麼一串數字有什麼含義呢,爲什麼要這樣命名,這就要從lsn說起。

我們知道postgresql通過lsn標識redo(xlog)位置,通過lsn可以定位到xlog文件以及文件的偏移量,下面先看看lsn,通過pg_current_xlog_location()函數可以查到當前的lsn位置(高版本是pg_current_wal_lsn),如下所示

postgres=# select pg_current_xlog_location();
 pg_current_xlog_location 
--------------------------
 5/285C6080
(1 row)

首先說下lsn的位數,因爲lsn標識着xlog的位置,這個位置在數據庫啓動後就是在不斷增加的,所以32位的lsn肯定是不夠用的。因爲32bit最大的日誌只能支撐4GB的日誌,這肯定是不夠用的,所以要考慮設計64位lsn,這就是現在的lsn格式,lsn由斜槓左邊和右邊各8位16進制數組成(斜槓左邊0省略了),也就是左邊32位,右邊32位,加起來64位,能夠支持4GB*4GB的日誌,這樣的lsn顯然是用不完的。

再來說說xlog文件名,總共24位數,都是16進制,可以分爲三部分,例如:00000001 00000005 00000028來說,第一部分代表時間線,時間線是備份恢復裏的概念,每當執行一次pg_rewind會造成時間線偏離分叉,時間線加1;第二部分代表logid,第三部分代表logseg,這兩部分其實就和lsn關聯起來了。

在這裏插入圖片描述

我們可能發現,logseg的八位數只有後面兩位有值,這是爲什麼呢?從上面這個公式上我們可以看出端倪,我們知道每個xlog是16M,lsn的低32位最大支持4GB的日誌,4GB/16M=256,這也是logseg的最大值,變爲16進制的話就是0x00-0xFF也就是xlog文件名的最後兩位16進制數正好滿足。所以xlog從00-FF共256個16M文件寫滿後,第二部分的logid字段加一,然後第三部分繼續從00-FF寫256個16M文件:00000001 00000000->00000001 000000FF->00000002 00000000->00000002 000000FF這樣的模式寫下去。

那麼我們再來看看上面這個公式的巧妙之處,xlog的第二段logid是LSN減一除以16M*256,首先lsn-1是因爲lsn不是從0開始的,他會跳過0從1開始。然後除以16M是除以logid,每個文件16M,再除256就是除以最後兩位的256,所以除下來的商其實就是xlog的第幾個文件,而第三部分除以256的餘數就是具體這個xlog文件中的偏移量。

那麼再來看看lsn的低32位,lsn的低32位除以16M的大小,16M等於2的24次方,285C6080除以2的24次方相當於向左移動6位,商就是logid,餘數就是xlog的偏移量,也就是28是logseg,也就是第一個圖中最後一個文件,當然老版本是xlog用時分配,新版本好像規則改成了xlog提前申請,會提前生成還未使用的xlog文件;而5C6080轉換爲10進制就是xlog中的位置,這個設計多麼巧妙啊,直接將xlog文件名用成了哈希表,直接定位lsn在哪個xlog以及在xlog中的偏移位。

其實postgresql也爲我們提供了函數能夠直接計算lsn在xlog中的位置:

postgres=# select pg_xlogfile_name_offset('5/285C6080');
      pg_xlogfile_name_offset       
------------------------------------
 (000000010000000500000028,6054016)
(1 row)

上面的計算結果也證實了這一點,logid=5,logseg=28,偏移量6054016(5C6080轉換爲10進制的值)。

歡迎關注我的公衆號:數據庫架構之美

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章