myrocks記錄格式分析

2021-09-23 17:43:39 字數 3427 閱讀 9769

title: mysql · myrocks · myrocks記錄格式分析

rocksdb作為kv儲存引擎,那麼myrocks記錄最終會以kv的形式儲存在rocksdb中。mysql中的表一般由若干索引組成, 在innodb儲存引擎中,每個索引對應一顆b樹,而在rocksdb儲存引擎中,索引對應於rocksdb中一段連續範圍的資料。

具體來說,這個範圍是此索引id和id+1之間的所有資料。如果表的所有索引都在乙個column family, 那錶的這些索引資料在物理上基本是連續的。

可以參考之前文章中的圖示

myrocks以索引為單位,將表的所有索引分別儲存在rocksdb中。

根據索引的型別,myrocks記錄的格式有所不同。下面以下表不同索引型別來分別介紹

create table t1(a int, 

b varchar(20),

c char(5),

d int,

pk int auto_increment,

primary key(pk) comment 'cf_1',

unique key idx2(b) comment 'cf_2')

engine= rocksdb;

insert into t1 (pk,a,b,c) values (1,1,'bbbbbbbbbb','c');

key: index_id, m(pk)

value: unpack_info, null-bitmap,b,c,d

key由索引id和主鍵組成。 index_id是索引的唯一標識占用4個位元組,m(pk) 表示pk轉化後的資料,此轉化後的資料可以直接用於memcmp比較

rocksdb資料都是根據key排序的,為了便於比較,不同型別資料都會經過一些轉化,轉化後可以直接用於memcmp比較。

關於memcmp轉化,下一節會詳細介紹

value儲存unpack_info和非主鍵外的其他字段資料, null-bitmap標識哪些欄位為空。

unpace_info儲存將m(pk)逆轉化為pk的資訊,如果不需要額外轉換資訊則unpace_info為null,此例中pk為int型別,不需要額外資訊unpace_info為null

key: index_id,null-byte, m(b),m(pk)

value: unpack_info

key由index_id,二級索引鍵和主鍵組成, 其中null-byte表示b是否為空。pk為主鍵非空,所以不需要null-byte

value只有unpack_info,表示 m(b),m(pk)逆轉化資訊,如果不需要額外轉換資訊則unpace_info為null。此例中b為varchar型別,需要額外資訊unpace_info不為null

唯一索引和普通二級索引儲存方式沒有區別

聯合索引每多乙個欄位會在字段前增加乙個null-byte,來表示此欄位是否為空

rocksdb為了比較方便,將key欄位轉化為可以直接memcmp比較的形式。所以myrocks 一般建議使用sensitive collations (latin1_bin, utf8_bin, binary).

這樣可以避免轉化的開銷。

整形轉化比較簡單,但對於有符號型別需要特殊處理,如果直接儲存會導致比較是負數比正數大。

這裡對有符號型別處理的方式是將符號位反轉,這樣正數就比負數大了,

關鍵**段如下

field_long::make_sort_key:

if (!table->s->db_low_byte_first)

char型別直接補空格

varchar型別為了節省空間處理起來就複雜多了

以原始碼中的注釋為例

const int varchar_cmp_less_than_spaces = 1;

const int varchar_cmp_equal_to_spaces = 2;

const int varchar_cmp_greater_than_spaces = 3;

example: if fpi->m_segment_size=5, and the collation is latin1_bin:

'abcd\0' => [ 'abcd' ]['\0 ' ]

'abcd' => [ 'abcd' ]

'abcd ' => [ 'abcd' ]

'abcdzzzz' => [ 'abcd' ][ 'zzzz' ]

字串以m_segment_size分段儲存,每段前m_segment_size-1個字元是內容,最後乙個字元表示和空格比較,varchar_cmp_equal同時也表示字串結束

例子中m_segment_size為5,實際實現上值為9

前面為我們看到的是進入rocksdb之前記錄的kv結構形式,實際上資料儲存到rocksdb後key還要進一步封裝

進入rocksdb之前的key稱為userkey, rocksdb內部稱為internalkey

internalkey=| user key (string) | sequence number (7 bytes) | value type (1 byte) |
其中sequence number 是記錄序列號,每個記錄sequence number根據是以記錄進入rocksdb先後順序遞增的。

sequence number是實現rocksdb事務處理的關鍵,這個下次討論。

value type是記錄的型別,put, merge,delete等

以例項來說明比較直觀,還是上面介紹的那個表,插入一條記錄,來看看記錄的具體結構

insert into t1 (pk,a,b,c) values (1,1,'bbbbbbbbbb','c');
檢視主鍵index_id為260,二級索引index_id為261

select * from information_schema.rocksdb_ddl where table_name='t1';

table_schema table_name partition_name index_name column_family index_number index_type kv_format_version cf

test t1 null primary 2 260 1 11 cf_1

test t1 null idx2 3 261 2 11 cf_2

二級索引記錄

MyRocks寫入分析

title mysql myrocks myrocks寫入分析 myrocks的寫入流程可以簡單的分為以下幾步來完成 將解析後的記錄 ktypevalue ktypedeletion 寫入到writebatch中 將wal日誌寫入log檔案 將writebatch中的內容寫到memtable中,事務...

MyRocks事務鎖分析

myrocks中rocksdb作為基於快照的事務引擎,其在事務支援上有別於innodb,有其自身的特點。在早期的月報 myrocks之事務處理 中,我們對鎖的實現有過簡單的分析,本文會以一些例子來介紹myrocks是如果來加鎖解鎖的。myrocks早期只支援排他鎖,支援selec.in share ...

MySQL 特性分析 MyRocks簡介

rocksdb是facebook基於leveldb實現的,目前為facebook內部大量業務提供服務。經過facebook大量工作,將rocksdb作為mysql的乙個儲存引擎移植到mysql,稱之為myrocks。經過兩年的發展,myrocks已經比較成熟 rc階段 現已進入了facebook m...