mysql小白系列_04 datablock
1.為什麽創建一個InnoDB表只分配了96K而不是1M?
2.解析第2行記錄格式?(用下面的表定義和數據做測試)
mysql> create table gyj_t3 (id int,name1 varchar(10),name2 varchar(10),name3 varchar(10),name4 varchar(10),name5 varchar(10)); Query OK, 0 rows affected (0.11 sec) mysql> insert into gyj_t3 (id,name1,name2,name3,name4) values(1,‘A‘,‘BB‘,‘CCC數據‘,‘DDDD‘); Query OK, 1 row affected (0.03 sec) mysql> insert into gyj_t3 values(3,‘aaaaaaaaaa‘,‘bbbbbbbbbb‘,‘ccccc‘,‘dddddd‘,‘e‘); Query OK, 1 row affected (0.06 sec) mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> insert into gyj_t3 values(4,‘aaaaaaaaaa‘,‘bbbbbbbbbb‘,null,‘dddddd‘,‘e‘); Query OK, 1 row affected (0.05 sec) mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM gyj_t3; +------+------------+------------+-------+--------+-------+ | id | name1 | name2 | name3 | name4 | name5 | +------+------------+------------+-------+--------+-------+ | 1| A | BB | CCC | DDDD | NULL | | 1 | aaaaaaaaaa | bbbbbbbbbb | ccccc | | NULL | | 3 | aaaaaaaaaa | bbbbbbbbbb | ccccc | dddddd | e | | 4 | aaaaaaaaaa | bbbbbbbbbb | NULL | dddddd | e | +------+------------+------------+-------+--------+-------+
3.詳細描述commit命令發出後,binlog日誌從內存寫到磁盤的過程序?
1.為什麽創建一個InnoDB表只分配了96K而不是1M?
- innodb在給數據分配存儲空間時,首先給32個的不連續的page
一個extent區是1M
- 如果32個page不夠用,再分配一段連續的64個page,也就是16384*64=1M,此後每次分配空間都是1M的整數倍
- 目的:
- 節省空間
- 小的undo 32個 page就夠了
問題:linux下查看一個ibd文件,大小是96K,也就是6個頁,那麽32個頁不是一次性給完而是用多少給多少?
-rw-rw----. 1 mysql mysql 8.6K Feb 12 08:38 t3.frm -rw-rw----. 1 mysql mysql 96K Feb 12 08:38 t3.ibd
32個page是524288字節,差不多是512KB,插入數據使文件達到500多kb時,下一次增長為1M的整數倍
2.解析第2行記錄格式?(用下面的表定義和數據做測試)
+------+------------+------------+-------+--------+-------+ | id | name1 | name2 | name3 | name4 | name5 | +------+------------+------------+-------+--------+-------+ | 1 | A | BB | CCC | DDDD | NULL | | 1 | aaaaaaaaaa | bbbbbbbbbb | ccccc | | NULL | | 4 | aaaaaaaaaa | bbbbbbbbbb | ccccc | dddddd | e | | 4 | aaaaaaaaaa | bbbbbbbbbb | NULL | dddddd | e | +------+------------+------------+-------+--------+-------+ create table t3 (id int,name1 varchar(10),name2 varchar(10),name3 varchar(10),name4 varchar(10),name5 varchar(10)); insert into t3 (id,name1,name2,name3,name4) values(1,‘A‘,‘BB‘,‘CCC‘,‘DDDD‘); insert into t3 (id,name1,name2,name3,name4) values(1,‘aaaaaaaaaa‘,‘bbbbbbbbbb‘,‘ccccc‘,‘‘); insert into t3 (id,name1,name2,name3,name4,name5) values(4,‘aaaaaaaaaa‘,‘bbbbbbbbbb‘,‘ccccc‘,‘dddddd‘,‘e‘); insert into t3 (id,name1,name2,name4,name5) values(4,‘aaaaaaaaaa‘,‘bbbbbbbbbb‘,‘dddddd‘,‘e‘);
- NULL不占空間
- ‘‘也不占空間
問題:NULL如何標誌哪些列是NULL的?
《MySQL技術內幕InnoDB存儲引擎》106頁及網上大部分都是提了一下,參考http://blog.csdn.net/linux_ever/article/details/64124868
第三行有NULL值,因為NULL標誌位不再是00而是06,轉換成二進制00000110,為1的值表示第2列和第3列的數據為NULL。其後存儲列數據的部分,沒有存儲NULL列,而只存儲了第1列和第4列的非NULL的值
*************************** 3. row ***************************
t1: d
t2: NULL
t3: NULL
t4: fff
3 rows in set (0.00 sec)
這裏的第2和第3列為NULL,NULL標誌位為06,二進制是00000110,是怎麽算出來2、3列的?
本次作業的第1、2行數據第5列為NULL,標誌位是20,二進制是00100000
第4行數據第4列為NULL,標誌位是08,二進制是00001000
int長度是4字節,其他可變長name長度是10字節,用多少長多少
https://www.cnblogs.com/wade-luffy/p/6289183.html
http://blog.csdn.net/beiigang/article/details/42175995
ibd文件格式如下
內容 | 16進制地址 |
---|---|
File Space Header | 0x0008 |
Insert Buffer Bitmap | 0x0005 |
File Segment Inode | 0x0003 |
Used Page | 0x45BF |
…… | 第N-4個塊 |
Used Page | 第N-3個塊 |
Free Page | 第N-2個塊 |
…… | 第N-2個塊 |
Free Page | 第N-2個塊 |
https://dev.mysql.com/doc/internals/en/innodb-page-overview.html
https://www.cnblogs.com/crossapply/p/5455620.html
行記錄格式
- compressed 壓縮頁,默認16K,可以壓縮成8K、4: alter table tabname row_format=compressed,key_block_size=8;
- Dynamic 存儲LOB/TEXT字段,由20字節+偏移量組成,本身不存儲數據,偏移量指向數據
- Compact 默認行記錄格式,超出行記錄長度時,由前綴768字節+偏移量組成,本身存儲部分數據,偏移量指向數據
- Redundant 廢棄
獲取ibd十六進制文本
hexdump -C -v t3.ibd > /tmp/t3.ibd.txt [root@docker01 tmp]# cat t3.ibd.txt |head -n 2 00000000 24 0a 12 cf 00 00 00 00 00 00 00 00 00 00 00 00 |$...............| 00000010 00 00 00 00 00 1a 25 e3 00 08 00 00 00 00 00 00 |......%.........| [root@docker01 tmp]# cat t3.ibd.txt |head -n 2048| tail -n 1024 |head -n 2 00004000 99 5f 47 61 00 00 00 01 00 00 00 00 00 00 00 00 |._Ga............| 00004010 00 00 00 00 00 1a 16 27 00 05 00 00 00 00 00 00 |.......‘........| [root@docker01 tmp]# cat t3.ibd.txt |head -n 3072| tail -n 1024 |head -n 2 00008000 c2 25 6e 67 00 00 00 02 00 00 00 00 00 00 00 00 |.%ng............| 00008010 00 00 00 00 00 1a 25 e3 00 03 00 00 00 00 00 00 |......%.........| [root@docker01 tmp]# cat t3.ibd.txt |head -n 4096| tail -n 1024 |head -n 2 0000c000 48 81 1b 2c 00 00 00 03 ff ff ff ff ff ff ff ff |H..,............| 0000c010 00 00 00 00 00 1a 3e 2e 45 bf 00 00 00 00 00 00 |......>.E.......| 截取第4頁 0000c000 48 81 1b 2c 00 00 00 03 ff ff ff ff ff ff ff ff |H..,............| 0000c010 00 00 00 00 00 1a 3e 2e 45 bf 00 00 00 00 00 00 |......>.E.......| 0000c020 00 00 00 00 00 0d 00 02 01 5b 80 06 00 00 00 00 |.........[......| 0000c030 01 29 00 02 00 03 00 04 00 00 00 00 00 00 00 00 |.)..............| 0000c040 00 00 00 00 00 00 00 00 00 1b 00 00 00 0d 00 00 |................| 0000c050 00 02 00 f2 00 00 00 0d 00 00 00 02 00 32 01 00 |.............2..| 0000c060 02 00 1f 69 6e 66 69 6d 75 6d 00 05 00 0b 00 00 |...infimum......| 0000c070 73 75 70 72 65 6d 75 6d 04 03 02 01 20 00 00 10 |supremum.... ...| 0000c080 00 2b 00 00 00 00 03 10 00 00 00 00 0b 52 b7 00 |.+...........R..| 0000c090 00 01 6b 01 10 80 00 00 01 41 42 42 43 43 43 44 |..k......ABBCCCD| 0000c0a0 44 44 44 00 05 0a 0a 20 00 00 18 00 3b 00 00 00 |DDD.... ....;...| 0000c0b0 00 03 11 00 00 00 00 0b 52 b7 00 00 01 6b 01 1e |........R....k..| 0000c0c0 80 00 00 01 61 61 61 61 61 61 61 61 61 61 62 62 |....aaaaaaaaaabb| 0000c0d0 62 62 62 62 62 62 62 62 63 63 63 63 63 01 06 05 |bbbbbbbbccccc...| 0000c0e0 0a 0a 00 00 00 20 00 41 00 00 00 00 03 12 00 00 |..... .A........| 0000c0f0 00 00 0b 52 b7 00 00 01 6b 01 2c 80 00 00 04 61 |...R....k.,....a| 0000c100 61 61 61 61 61 61 61 61 61 62 62 62 62 62 62 62 |aaaaaaaaabbbbbbb| 0000c110 62 62 62 63 63 63 63 63 64 64 64 64 64 64 65 01 |bbbcccccdddddde.| 0000c120 06 0a 0a 08 00 00 28 ff 47 00 00 00 00 03 13 00 |......(.G.......| 0000c130 00 00 00 0b 52 b7 00 00 01 6b 01 3a 80 00 00 04 |....R....k.:....| 0000c140 61 61 61 61 61 61 61 61 61 61 62 62 62 62 62 62 |aaaaaaaaaabbbbbb| 0000c150 62 62 62 62 64 64 64 64 64 64 65 00 00 00 00 00 |bbbbdddddde.....| ..... 0000fff0 00 00 00 00 00 70 00 63 8b 8a 26 91 00 1a 3e 2e |.....p.c..&...>.|hexdump
3.詳細描述commit命令發出後,binlog日誌從內存寫到磁盤的過程序?
- 先做write操作
- 日誌會被write到每個線程對應的文件句柄的緩存中,也就是標準的IO緩存中
- 每個線程會緩存到自己的IO緩存中,每個線程產生的日誌其他線程是不可見的
此時發生宕機,日誌丟失,臟塊丟失
- 再做flush操作
- 將私有緩存中的日誌寫到公共可見的操作系統文件緩存,此時不同線程都可以看到其他線程的日誌內容
此時宕機,依然丟失數據
- 最後做sync持久化
- 將日誌從內存中寫到硬盤
sync_binlog 1 多少次事務一起寫binlog
innodb_flush_log_at_trx_commit 1 寫redolog
索引:
- 主鍵索引
- 非空唯一索引
- 都沒有的話走6字節的rowid,但是不能作為where過濾條件
index organized table索引組織表:數據就在葉子節點上,檢索數據不需要回行
回行,先找到索引所在位置,根據索引再一次找到數據 二級索引、輔助索引,葉子節點只存儲索引信息,葉子上帶著的信息指向數據所在的主鍵索引的位置
innodb邏輯存儲結構: tablespace - segement - extent - page - row
表空間是否獨立 innodb_file_per_table,默認為ON
如果是獨立表空間,一張表一個表空間
如果是off,就全部放在ibdata1裏面了
查看表ID ,0 代表的是系統表空間 select * from innodb_sys_tables
-
tablespace指的是共享表空間ibdata1,存儲的是undo、插入緩沖索引頁、系統事務、double write buffer,因為寫undo原因,大小隨時變化
-
ib_logfile,每個表自己的空間:數據(跟主鍵索引一起存放)、輔助索引、插入緩存bitmap
-
插入緩沖
- 主鍵索引和數據放在一起,其他索引放在索引頁
- 往輔助索引頁寫東西時,每個被寫入的頁先放在buffer存著
- 一旦有需要被寫入的索引頁讀入了內存,這是把buffer裏存著的東西一起寫進去
-
segement 段
- 段等於表,段是數據的物理存儲形式,表是數據的邏輯定義
- 數據段,聚簇索引,數據段在B-tree的葉子結點
- 索引段,非葉子結點就是索引
-
extent 區
- 一個extent是1M,是分配空間的最小單位
- 1M由64個連續的page組成,一個page是16K
- innodb為保證extent連續,一次申請多個
- 一個extent由多個page組成
-
page 頁,類似存儲塊大小
- 最小的IO單位
- page默認大小是16K innodb_page_size = 16384
- ROW 行
- 事務ID、回滾指針、數據、索引
innodb文件結構
表的組成:
- tabname.ibd 表數據
- File Space Header
- tabname.frm 表結構
hexdump -C -v tabname.ibd 一個page 16K,16進制一行有16個字節,那麽一個page就有1024行 查看第一個塊
hexdump -C -v tabname.ibd |head -n 1024 | head -n 2
2塊
hexdump -C -v tabname.ibd |head -n 2048 |tail -n 1024
3塊
hexdump -C -v tabname.ibd |head -n 3072 |tail -n 1024
mysql小白系列_04 datablock