postgresql集羣方案hot standby初級測試(五)——xlog詳細解釋record

上一篇文章講了下xlog的頭部,今天詳細講解下record部分,希望這兩篇文章對研究postgresql的xlog的同學有所幫助:


本文來自:http://blog.csdn.net/lengzijian/article/details/7840332


首先看下XLOG日誌記錄結構:


XLogRecord記錄了XLOG的相關控制信息,數據結構如下:

typedef struct XLogRecord

{

        pg_crc32        xl_crc;                 /* 本條記錄的CRC校驗碼 */                                                                                                                                                       

        XLogRecPtr      xl_prev;                /* 日誌的前一條記錄 */

        TransactionId xl_xid;                     /* 事務ID */

        uint32          xl_tot_len;             /* 整條記錄的總長度*/

        uint32          xl_len;                 /* 組員管理器的數據長度*/

        uint8           xl_info;                /* 信息標誌位 */

        RmgrId          xl_rmid;         /* 資源管理器IDtypedef uint8 RmgrId;*/

} XLogRecord;


        其中,資源管理器ID主要用於日誌系統中,數據庫系統把各種需要記錄日誌的數據分類,分配給他們對應的資源管理號,系統在回覆或者讀取日誌記錄時,能夠很方便地知道該日誌記錄的元數據屬於哪一類,結合信息標誌位(xl_info)信息,就能知道數據庫對元數據做的是那種操作。共有16中資源(有幾項還不清楚是做什麼用的):

#define RM_XLOG_ID         0       該條日誌記錄的是一個檢查點信息。                                                                                                                                         

#define RM_XACT_ID           1       該條日誌記錄的是一個事物的提交或者終止信息

#define RM_SMGR_ID          2      

#define RM_CLOG_ID          3       CLOG中某一頁的初始化

#define RM_DBASE_ID          4

#define RM_TBLSPC_ID          5

#define RM_MULTIXACT_ID       6

#define RM_RELMAP_ID         7

#define RM_STANDBY_ID        8

#define RM_HEAP2_ID          9

#define RM_HEAP_ID         10       該條日誌記錄的是對隊中元組進行修改的信息

#define RM_BTREE_ID        11       該條日誌記錄的是對BTree進行修改

#define RM_HASH_ID        12

#define RM_GIN_ID          13

#define RM_GIST_ID         14

#define RM_SEQ_ID          15


        信息標誌位(xl_info)的高四位由資源管理器使用,表示該日誌是哪種類型的日誌,低四位表示對應的塊是否需要備份,對於高四位,信息有如下幾種:

/* include/access/xact.h

 * XLOG allows to store some information in high 4 bits of log

 * record xl_info field

 */

#define XLOG_XACT_COMMIT               0x00          //事務提交

#define XLOG_XACT_PREPARE               0x10         //預備

#define XLOG_XACT_ABORT                 0x20         //事務取消

#define XLOG_XACT_COMMIT_PREPARED      0x30         //準備提交事務

#define XLOG_XACT_ABORT_PREPARED        0x40         //準備取消事務

#define XLOG_XACT_ASSIGNMENT            0x50        //不詳。。。(之後補充)

 

 

/*include/access/htup.h

 * WAL record definitions for heapam.c's WAL operations

 * XLOG allows to store some information in high 4 bitsof log

 * record xl_info field.  We use 3 for opcode and one for init bit.

 */

#define XLOG_HEAP_INSERT        0x00            //插入元組日誌

#define XLOG_HEAP_DELETE       0x10            //刪除元組日誌

#define XLOG_HEAP_UPDATE       0x20            //更新元組日誌

 

細心的同學會發現,下面的元組操作和上面的事務操作的編碼(0x00)重複了,不要忘記之前我們說過,要通過xl_rmid字段來判斷屬於何種操作:先判斷屬於那種操作,在做具體的操作內容。


低四位中只用了位,具體如下(可以看到最後一位沒有用到):

/*include/access/xlog.h

 * If we backed up any disk blocks with the XLOG record, we use flag bits in                                                                                                                                                                         

 * xl_info to signal it.  We support backup of up to 3 disk blocks per XLOG

 * record.

 */

#define XLR_BKP_BLOCK_MASK              0x0E    /* all info bits used for bkp blocks */

#define XLR_MAX_BKP_BLOCKS              3

#define XLR_SET_BKP_BLOCK(iblk) (0x08 >> (iblk))

#define XLR_BKP_BLOCK_1                 XLR_SET_BKP_BLOCK(0)    /* 0x08 */

#define XLR_BKP_BLOCK_2                 XLR_SET_BKP_BLOCK(1)    /* 0x04 */

#define XLR_BKP_BLOCK_3                 XLR_SET_BKP_BLOCK(2)    /* 0x02 */

 

日誌記錄數據信息:

        rmgr data 數據被XLogInsert()函數寫入,有一個或多個XlogRecData數據結構組成,當有多個XLogRecData結構體時有兩種情況:1.源數據沒有在內存上物理相鄰;2.數據在多個緩衝區中被指定。

 

       如果buffer有效,那麼XLOG將會檢查buffer是否必須備份(即,是否該buffer自最後一次checkpoint以來,第一次被更改)。如果是這樣,那麼整個頁面內容會被附加到XLOG日誌中,同時,XLOG在標誌位xl_info中設置XLR_BKP_BLOCK_X位。注:buffer備份後,我們不能夠通過XLogRecData結構體插入數據到XLOG記錄中,因爲我們假定他已經在buffer中了,因此rmgr的redo操作必須注意XLR_BKP_BLOCK_X的值,以便指導XLOG記錄中到底存的是什麼。

 

如果buffer有效,調用者必須設置buffer_std(緩衝區存儲標準),來表明頁面是否用標準pd_lower/pd_upper頭字段。

 

日誌記錄中的數據信息存儲在結構XlogRecData中(結構體如下):

typedef struct XLogRecData

{

        char       *data;                       /* 資源管理器數據 */

        uint32          len;                    /* 資源管理器數據的長度 */                                                                                                                                                             

        Buffer          buffer;                 /* 該數據涉及的緩衝區*/

        bool            buffer_std;             /* 緩衝區存儲標準 */

        struct XLogRecData *next;                /* 下一個節點指針 */

} XLogRecData;


        這裏保存了所有操作信息,在閱讀了xlogdump源碼之後發現,讀取xlog記錄不需要XLogRecData結構體,例如讀取插入操作時,只需要調用xl_heap_insert結構體就可以取出數據。

 

        例如執行了一次insert,用xlogdump可以讀出下面的代碼(同樣的updata、delete以及事務操作commit和abort都在改數據內):

INSERT: 2 row(s) found in the table `t_user'.           //有兩個字段在表“t_user”中

INSERT: column 0, name userid, type 1043, value '14541'//包括字段名,字段類型,字段的值都會在數據中取出,如果想了解具體細節可以看xlogdump的源碼。

INSERT: column 1, name name, type 1043, value 'lengzijian'

 

XLOG記錄中的備份數據塊的頭部信息保存在BkpBlock中,數據結構如下:

typedef struct BkpBlock

{

        RelFileNode node;                       /* 表節點*/                                                                                                                                                                                                 

        ForkNumber      fork;                   /* 關係分支*/

        BlockNumber block;                      /* 塊數 */

        uint16          hole_offset;             /* "hole"偏移值 */

        uint16          hole_length;             /* "hole"長度 */

        /* 實際的塊數據在結構體之後 */

} BkpBlock;

 

在用xlogdump工具時,發現一個問題,就是更新或插入時,有時不能夠打印出statements,例如:

lengzijian-----------record->xl_len[21]/SizeOfHeapUpdate:[28]/SizeOfHeapHeader:[5]

//這裏我打印出他的判斷信息,由於(21 – 28 – 5)的無符號型大於MaxHeapTupleSize

//所以退出,沒有打印出statements.

[cur:0/4C6F0960, xid:5215584, rmid:10(Heap), len/tot_len:21/2781, info:9, prev:0/4C6F0910] insert: s/d/r:pg_default/lengzijian/t_user blk/off:758/61 header: none

 

[cur:0/4C6F0960, xid:5215584, rmid:10(Heap), len/tot_len:21/2781, info:9, prev:0/4C6F0910] bkpblock[1]: s/d/r:pg_default/lengzijian/t_user blk:758 hole_off/len:268/5484

//根據如上分析:是由於已經把數據備份到bkpblock[1]中,通過觀察日誌也可以看到,在之後,xlogdumpbkpblock也打印出來,說明xl_info的後低四位被設置了。

 

下一篇講解xlogdump工具的使用和部分源碼分析。


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