00 -表_映射_日志_事件
Table_map_log_Event是行格式Binlog中的一種事件。它記錄了表的元數(shù)據(jù)信息。如數(shù)據(jù)庫(kù)名、表名和字段類型。從機(jī)執(zhí)行行事件時(shí),表映射日志事件的功能如下:
-根據(jù)數(shù)據(jù)庫(kù)名和表名,在從機(jī)上打開(kāi)相應(yīng)的表
-檢查從屬設(shè)備上的表的字段類型是否與主設(shè)備上的表的字段類型兼容。如果沒(méi)有,從機(jī)將報(bào)告錯(cuò)誤。
-將數(shù)據(jù)轉(zhuǎn)換為從屬表上的字段類型。然而,轉(zhuǎn)換僅限于從機(jī)和主機(jī)的場(chǎng)類型兼容的情況。
01-生成table _ map _ log _ event
Table_map_log_event的單位是語(yǔ)句。在語(yǔ)句記錄第一行事件之前,將為每個(gè)要更新的表生成一個(gè)表映射日志事件。因此,binlog中的Table_map_log_event具有以下特征:
-Table_map_log_event先于所有行事件
語(yǔ)句的行格式事件如下所示:
Query_log_event("BEGIN ")
db1.t1的Table_map_log_event //表
db1.t2的Table_map_log_event //表
db1.t1的Update_rows_log_event //更新
db1.t2的Update_rows_log_event //更新
Xid_log_event
-當(dāng)語(yǔ)句不生成行事件時(shí),不會(huì)生成Table_map_log_event。
這是因?yàn)樵谏傻谝恍惺录r(shí),會(huì)生成Table_map_log_event。這確保了當(dāng)語(yǔ)句不產(chǎn)生任何更新時(shí),binlog中不會(huì)記錄任何事件。
-也可以記錄Table_map_log_event,而不是生成row事件
記錄Table_map_log_event時(shí),無(wú)法確定表是否會(huì)更新數(shù)據(jù)。因此,將為所有具有寫(xiě)鎖定的表生成Table_map_log_event。當(dāng)您看到以下binlog內(nèi)容時(shí),不要感到驚訝:
Query_log_event("BEGIN ")
db1.t1的Table_map_log_event //表
db1.t2的Table_map_log_event //表
db1.t1的Update_rows_log_event //更新
Xid_log_event
-參考代碼
在sql/handler.cc中寫(xiě)入_ locked _ table _ maps()和binlog_log_row()..
02-table_map_log_event格式
table_map_log_event格式如下圖所示:
-包裝_長(zhǎng)度
首先,介紹了常用的術(shù)語(yǔ)pack_length。是一種數(shù)值存儲(chǔ)方式,常用于二進(jìn)制日志和MySQL的通訊包中。為了減少存儲(chǔ)和傳輸過(guò)程中占用的空,長(zhǎng)度字段和整形值以可變長(zhǎng)度的方式存儲(chǔ)。具體算法是:
-小于251的值
用1個(gè)字節(jié)直接存儲(chǔ)該值
-251或以上和65535或以下(0xff)
首先,一個(gè)字節(jié)用于存儲(chǔ)值252,然后兩個(gè)字節(jié)用于存儲(chǔ)值。
-大于65535且小于或等于16777215(0xFFF)的值
首先,將值253存儲(chǔ)在1字節(jié)中,然后將值存儲(chǔ)在3字節(jié)中。
-大于16777215的值
值254首先存儲(chǔ)在一個(gè)字節(jié)中,然后存儲(chǔ)在八個(gè)字節(jié)中。
在大多數(shù)情況下,如果該值小于251,這種存儲(chǔ)方法可以保存空。同時(shí)可以支持?jǐn)?shù)值大的情況。
-參考代碼
SQL-common/pack.c中的net_store_length()
-事件標(biāo)題
和其他事件一樣。
-表格id
表id就像表的主鍵,它唯一地標(biāo)識(shí)了一個(gè)table_map_log_event。要保存空,數(shù)據(jù)庫(kù)名和表名不會(huì)記錄在row事件中,但只會(huì)記錄一個(gè)表id。通過(guò)將table_map_log_event與表id相關(guān)聯(lián),您可以知道生成了哪個(gè)表。
旗幟
當(dāng)前未使用,內(nèi)容始終為0,占2字節(jié)。
-數(shù)據(jù)庫(kù)名稱長(zhǎng)度
數(shù)據(jù)庫(kù)名稱的長(zhǎng)度,不包括“0”。使用包裝長(zhǎng)度進(jìn)行儲(chǔ)存。
-數(shù)據(jù)庫(kù)名稱
數(shù)據(jù)庫(kù)的名稱以“0”結(jié)尾,因此空之間占用的空間是數(shù)據(jù)庫(kù)名稱長(zhǎng)度+1字節(jié)。
-表名長(zhǎng)度
表名長(zhǎng)度,不包括“0”。使用包裝長(zhǎng)度進(jìn)行儲(chǔ)存。
-表名
表的名稱以“0”結(jié)尾,因此空之間占用的空間是表名長(zhǎng)度+1字節(jié)。
-列數(shù)
字段數(shù)量。使用包裝長(zhǎng)度進(jìn)行儲(chǔ)存。
-列類型
這里的字段類型不是SQL語(yǔ)句中的類型,而是MySQL內(nèi)部的數(shù)據(jù)類型。后面會(huì)詳細(xì)介紹。每個(gè)字段的類型占用一個(gè)字節(jié),總長(zhǎng)度等于字段數(shù)。類型存儲(chǔ)的順序是根據(jù)主表中字段的順序生成的。因此,如果從表上的字段順序發(fā)生變化,將會(huì)導(dǎo)致錯(cuò)誤。
-元數(shù)據(jù)長(zhǎng)度
字段的元數(shù)據(jù)長(zhǎng)度。使用包裝長(zhǎng)度進(jìn)行儲(chǔ)存。
-元數(shù)據(jù)
除了類型,字段還有長(zhǎng)度等屬性。這些屬性信息存儲(chǔ)在元數(shù)據(jù)中,這將在后面詳細(xì)描述。
-空標(biāo)志
字段是否可以是空的屬性,每個(gè)字段占用一位。因?yàn)槿罩臼且宰止?jié)為最小單位記錄的,所以當(dāng)尾部小于1字節(jié)時(shí),它被存儲(chǔ)為1字節(jié)。比如有9個(gè)字段,前8個(gè)字段占用一個(gè)字節(jié),后一個(gè)字段也需要占用一個(gè)字節(jié),總共2個(gè)字節(jié)。存儲(chǔ)順序如下:第一個(gè)字節(jié)存儲(chǔ)主機(jī)上第1-8個(gè)字段的null屬性,第二個(gè)字節(jié)存儲(chǔ)第9-16個(gè)字段的null屬性,依次推送。在一個(gè)字節(jié)中,8個(gè)字段的空屬性按字段順序從低到高排列。例如:01010101,左邊第一位是第一個(gè)字段的null屬性,依次推送。代碼在log_event.cc的Table_map_log_event()中..如下圖所示:
03-table _ map _ log _ event中的字段類型
table_map_log_event中存儲(chǔ)的字段類型是MySQL內(nèi)部類型。了解內(nèi)部類型和SQL數(shù)據(jù)類型的關(guān)系,可以幫助我們更好的理解MySQL的實(shí)現(xiàn)。下圖顯示了SQL數(shù)據(jù)類型和MySQL內(nèi)部類型的對(duì)應(yīng)關(guān)系:
- TINYINT/BOOL
BOOL只是TINYINT的別名。
- CHAR/BINARY
除了不同的字符集之外,CHAR和BINARY具有相同的特性。因此,它們使用相同的內(nèi)部類型,并通過(guò)字符集屬性進(jìn)行區(qū)分。BINARY(N)等價(jià)于CHAR(N) CHARSET binary。
-VARCHAR/VARBINIC
類似于CHAR/BINARY
-枚舉/設(shè)置
應(yīng)該特別注意這一點(diǎn)。Table_map_log_event中的ENUM/SET與CHAR的類型相同,是MYSQL_TYPE_STRING。實(shí)際類型信息存儲(chǔ)在元數(shù)據(jù)中。這三種類型可以通過(guò)元數(shù)據(jù)中的類型信息來(lái)區(qū)分。
-TINYBOB/BLOB/
-MEDIUMBLOB/long lob/
- TINYTEXT/TEXT/
-MEDIUMTExt/LOTEXT
文本和BLOB之間的關(guān)系類似于CHAR和BINARY。不同BLOB/TEXT類型之間的唯一區(qū)別是最大長(zhǎng)度。因此,所有BLOB/TEXT字段在內(nèi)部都由相同的類型表示。這種類型的字符集屬性可以區(qū)分BLOB和TEXT。該類型還有一個(gè)最大長(zhǎng)度屬性,可以區(qū)分TINYBLOB和其他BLOB。信息的最大長(zhǎng)度存儲(chǔ)在元數(shù)據(jù)中。
04-不同字段的元數(shù)據(jù)
元數(shù)據(jù)按照主文檔中字段的順序記錄字段的元數(shù)據(jù)(屬性)信息。元數(shù)據(jù)信息具有以下特征:
-不同類型的字段可能有不同的屬性信息和不同的長(zhǎng)度。
-某些類型沒(méi)有屬性信息。
-任何類型的元數(shù)據(jù)信息的長(zhǎng)度總是固定的。
根據(jù)列類型中的類型信息,我們可以知道每種類型的元數(shù)據(jù)信息。元數(shù)據(jù)中的元數(shù)據(jù)格式如下圖所示:
C1的元數(shù)據(jù)占用2字節(jié),C2的類型沒(méi)有元數(shù)據(jù),所以不占用空。C3的元數(shù)據(jù)只有一個(gè)字節(jié),C4占用兩個(gè)字節(jié)。
除以下類型外,所有其他類型都沒(méi)有元數(shù)據(jù)。
- MYSQL_TYPE_FLOAT
1字節(jié),內(nèi)容:sizeof(浮點(diǎn))。
- MYSQL_TYPE_DOUBLE
1字節(jié),內(nèi)容:sizeof(double)。
- MYSQL_TYPE_NEWDECIMAL
2字節(jié),第一個(gè)字節(jié)是精度,第二個(gè)字節(jié)存儲(chǔ)小數(shù)位。
- MYSQL_TYPE_BIT
2字節(jié),第一個(gè)字節(jié)為(位長(zhǎng))/8,第二個(gè)字節(jié)為(位長(zhǎng))%8。
- MYSQL_TYPE_VARCHAR
2字節(jié),存儲(chǔ)長(zhǎng)度。- MYSQL_TYPE_BLOB
1字節(jié),存儲(chǔ)blob的最大長(zhǎng)度,單位字節(jié)。內(nèi)容:1、2、3或4。
- MYSQL_TYPE_JSON
- MYSQL_TYPE_GOMETRY
這兩種類型都是從BLOB繼承的,所以元數(shù)據(jù)內(nèi)容和MYSQL_TYPE_BLOB是一樣的。
- MYSQL_TYPE_STRING
2字節(jié)。
-當(dāng)實(shí)際類型為ENUM或SET時(shí),第一個(gè)字節(jié)存儲(chǔ)實(shí)類型MYSQL_TYPE_ENUM或MYSQL_TYPE_SET,第二個(gè)字節(jié)存儲(chǔ)長(zhǎng)度。
-當(dāng)實(shí)際類型為CHAR時(shí),使用2個(gè)字節(jié)來(lái)存儲(chǔ)長(zhǎng)度。為了避免與ENUM/SET的第一個(gè)字節(jié)沖突,采用了一種特殊的編碼方法。
-參考代碼
函數(shù)do_save_field_metadata()在sql/field.cc中
注意:本文代碼參考的是MySQL-5.7中的代碼,其他版本可能不一致。
推薦訂閱原作者宋立兵在微信官方賬號(hào)的MySQL代碼研究
1.《mediumblob Table_map_log_event內(nèi)容詳解》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識(shí),僅代表作者本人觀點(diǎn),與本網(wǎng)站無(wú)關(guān),侵刪請(qǐng)聯(lián)系頁(yè)腳下方聯(lián)系方式。
2.《mediumblob Table_map_log_event內(nèi)容詳解》僅供讀者參考,本網(wǎng)站未對(duì)該內(nèi)容進(jìn)行證實(shí),對(duì)其原創(chuàng)性、真實(shí)性、完整性、及時(shí)性不作任何保證。
3.文章轉(zhuǎn)載時(shí)請(qǐng)保留本站內(nèi)容來(lái)源地址,http://f99ss.com/jiaoyu/819683.html