MySQL:Innodb中數字的儲存方式

gaopengtttt發表於2020-07-28

一、問題來源

如果我們檢視show egnine innodb檢視鎖記錄的時候往往會看到Innodb的數字使用類似
80000001的形式顯示如下:

Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 1; hex 31; asc 1;;
 1: len 1; hex 31; asc 1;;
 2: len 1; hex 80; asc  ;;
 3: len 8; hex 8000000000000001; asc         ;;

這裡是一個有符號的bigint的顯示。本文就來說一下這個值是這麼計算出來的。本文以4位元組的int為例。

二、原始碼部分

關於轉換的部分主要集中在函式row_mysql_store_col_in_innobase_format中,我們來看一下數字的轉換程式碼如下:

if (type == DATA_INT) {
        /* Store integer data in Innobase in a big-endian format,
        sign bit negated if the data is a signed integer. In MySQL,
        integers are stored in a little-endian format. */
        byte*    p = buf + col_len; //p指標指向buf的 最高地址, 反向獲取資料 得到大端 buffer是
        for (;;) {
            p--;
            *p = *mysql_data; //轉大端 
            if (p == buf) { //如果儲存完成 
                break;
            }
            mysql_data++;
        }
        if (!(dtype->prtype & DATA_UNSIGNED)) {//如果為有符號型別
            *buf ^= 128;
        }
        ptr = buf; //PTR指向 buffer低地址
        buf += col_len;//buf指向 buffer的高地址
    } 
...
dfield_set_data(dfield, ptr, col_len); //存入dtuple中,裡面很簡單就是取void* 存進去進行了。

這裡的關鍵部分就是對於有*buf ^= 128;這部分,實際上就是轉換為大端後的最低位做一個異或操作。
最終操作為函式page_cur_tuple_insert會將這個dtuple插入到實際的資料檔案其中有一個函式為rec_convert_dtuple_to_rec_comp,會獲得最終的物理記錄,其中的程式碼memcpy(end, dfield_get_data(field), len);可以看到實際存入物理記錄的就是這裡的轉換後的值。

三、例項解析

1. 有符號

正數:以數字5為例子,其4位元組的表示方法為0x05 0x00 0x00 0x00,這裡還是小端形式為MySQL層傳入的值。Innodb轉換方式如下:

  • 從高地址開始取,轉換為大端形式,轉換後為
    0x00 0x00 0x00 0x05
  • 如果為有符號型別轉換為大端後的最低位做一個異或操,轉換為
    0x80 0x00 0x00 0x05

負數:以數字-5為例子,其4位元組的表示方法為0xfb 0xff 0xff 0xff(補碼),這裡還是小端形式為MySQL層傳入的值。Innodb轉換方式如下:

  • 從高地址開始取,轉換為大端,轉換後為
    0xff 0xff 0xff 0xfb
  • 如果為有符號型別轉換為大端後的最低位做一個異或操,轉換為
    0x7f 0xff 0xff 0xfb
2、無符號

這個比較簡單,直接原始值大端輸出即可,不做最後的異或操作。

四、測試

我們為了測試就建立一個表如下:

create table testint(id int primary key);
insert into testint values(5),(-5);

然後使用innblock和bcview檢視二進位制檔案中儲存的方式。

第一行記錄為:
image.png

轉換如下:
80000005 實際記錄5
000000014224 trx id
bd000000230110 roll ptr

第二行記錄為:
image.png

7ffffffb 實際記錄-5
000000014224 trx id
bd00000023011d roll ptr

我們可以發現我們的分析是正確,確實物理檔案中也是這樣儲存的。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2707568/,如需轉載,請註明出處,否則將追究法律責任。

相關文章