《Mysql Binlog事件結構》要點:
本文介紹了Mysql Binlog事件結構,希望對您有用。如果有疑問,可以聯系我們。
這個部分描述了事件被寫入binlog或者delay log中的屬性.所有的事件有相同的整體結構,也就是包括事件頭和事件數據:
+===================+| event header |+===================+| event data |+===================+
具體的內容隨著Mysql版本的升級而不同,這導致了binlog格式的不一致:
v1:用于3.23版本
v3:用于4.0.2到4.1版本
v4:用于5.0及以上版本
v2的格式用于4.0.x的版本中,但是已經過期了,并且不再支持了.
有些變亂的結構隨著版本沒有改變,而有些與版本有關.在所有的版本中,不同類型的變亂在數據部分的結構不一樣.
日志文件的第一個事件是特殊的.他是個符號事件,包括binlog版本和服務器版本.符號事件中的信息讓程序能夠決定日志文件的格式,這樣剩余的事件內容才能被正確的解析出來.
下面說明下不同版本的binlog格式:
v1變亂結構:
+=====================================+| event | timestamp 0 : 4 || header +----------------------------+| | type_code 4 : 1 || +----------------------------+| | server_id 5 : 4 || +----------------------------+| | event_length 9 : 4 |+=====================================+| event | fixed part 13 : y || data +----------------------------+| | variable part |+=====================================+
頭長度=13字節,數據長度=(變亂長度-13)字節,y與變亂類型有關.
v3變亂結構
+=====================================+| event | timestamp 0 : 4 || header +----------------------------+| | type_code 4 : 1 || +----------------------------+| | server_id 5 : 4 || +----------------------------+| | event_length 9 : 4 || +----------------------------+| | next_position 13 : 4 || +----------------------------+| | flags 17 : 2 |+=====================================+| event | fixed part 19 : y || data +----------------------------+| | variable part |+=====================================+
頭長度=19字節,數據長度=(變亂長度-19)字節,y與變亂類型有關.
v4變亂結構
+=====================================+| event | timestamp 0 : 4 || header +----------------------------+| | type_code 4 : 1 || +----------------------------+| | server_id 5 : 4 || +----------------------------+| | event_length 9 : 4 || +----------------------------+| | next_position 13 : 4 || +----------------------------+| | flags 17 : 2 || +----------------------------+| | extra_headers 19 : x-19 |+=====================================+| event | fixed part x : y || data +----------------------------+| | variable part |+=====================================+
頭長度=x字節,數據長度=(變亂長度-x)字節,固定數據部分長度=y字節,變量數據程度=(變亂長度-(x+y))字節.x由FDE(格式描述變亂format description event)header_length給出.當前來說,x=19,所以extra_headers字段是空的.
y和變亂類型有關,也是由FDE給出的.fixed-part的長度對于同一個變亂類型是一樣的,但是不同的變亂類型是不一樣的.
fixed-part有時候指的是post-header,變量部分有時候指的是payload或者body.
一、變亂內容-寫入約定
變亂內容的寫入約定如下:
數字是依照地位優先的格式寫入的(最不重要字節有限),除非顯式表示
表示位置或長度的值以字節形式寫入,并且是無符號的
有些數字是以封包整數的形式寫入的,這個格式后面再詳細說明
字符串有以下幾種格式:
字符串可能寫入一個固定長度域中,右邊以null填充(0x00)
可變長度的字符串前面包括一個表示字符串長度的內容
有些可變長度的字符串以null結尾,有些不是.每個字符串中有符號表示屬于哪種情況.
對于null結尾的字符串,最前面是字符串長度,這個長度不包括結尾的null字節,除非顯式表明
如果存在可變長度的字符串在變亂結尾,并且變亂前面沒有任何內容,這個字符串的長度=變亂長度-變亂中其他內容的長度.
有些變亂使用封包整數,這是一個特殊的格式,用來有效的描述無符號整數.封包整數可以存儲一個8字節的整數,小整數(small integer)占用1、3或4字節.根據下面的表格,第一個字節的值決定了如何讀這個數字:
第一個字節 | 格式 |
---|---|
0-250 | 第一個字節就是數字(0-250),不必要額外的字節. |
252 | 使用多于2字節,數字的范圍是251-0xffff |
253 | 使用多于3字節,數字的范圍是0xffff-0xfffff |
254 | 使用多于8字節,數字范圍是0xfffff-0xffffffffffffffff |
二、事件頭字段
每個變亂以LOG_EVENT_HEADER_LEN長度開頭,這個常量在v1格式中時13,在v3及以上格式中是19.
v1:13字節:timestamp+type code+server ID+event length
v3:19字節:v1的字段+next position+flags
v4:19字節或更多:v3的字段+可能有其他信息
v1變亂頭:
+============================+| timestamp 0 : 4 |+----------------------------+| type_code 4 : 1 |+----------------------------+| server_id 5 : 4 |+----------------------------+| event_length 9 : 4 |+============================+
v1頭的13個字節也包括在其他版本的事件頭中.
v3變亂頭
+============================+| timestamp 0 : 4 |+----------------------------+| type_code 4 : 1 |+----------------------------+| server_id 5 : 4 |+----------------------------+| event_length 9 : 4 |+----------------------------+| next_position 13 : 4 |+----------------------------+| flags 17 : 2 |+============================+
和v1對比,v3以上中的事件頭中包括兩個額外的字段,總長度為19字節.
v4變亂頭
+============================+| timestamp 0 : 4 |+----------------------------+| type_code 4 : 1 |+----------------------------+| server_id 5 : 4 |+----------------------------+| event_length 9 : 4 |+----------------------------+| next_position 13 : 4 |+----------------------------+| flags 17 : 2 |+----------------------------+| extra_headers 19 : x-19 |+============================+
v4的事件頭中包括一個extra_headers字段,是為了以后擴展用.當前x=19,所以v4和v3當前格式一樣.
注意:extra_headers么有在FORMAT_DESCRIPTION_EVENT或ROTATE_EVENT的頭中出現.
在log_event.h中,包括幾個事件頭的常量:
EVENT_TYPE_OFFSET = 4
SERVER_ID_OFFSET = 5
EVENT_LEN_OFFSET = 9
LOG_POS_OFFSET = 13
FLAGS_OFFSET = 17
事件頭中包括以下信息:
timestamp
4字節.表示的是語句開始執行的時間,格式與TIMESTAMP SQL數據類型一樣.
type_code
1字節.變亂類型.1表示START_EVENT_V3,2表示QEURY_EVENT,以此類推.這些數字定義在log_event.h的Log_event_type的枚舉類中.
server id
4字節,產生這個變亂的mysqld服務器id.這個是在服務器中配置文件配置的,用于主從復制.server id會在循環復制時避免死循環(開啟了--log-slave-updates配置).假設M1、M2和M3的server id分別是1、2、3,而且他們循環復制:M1是M2的主,M2是M3的主,M3是M1的主.他們的主從關系如下:
M1---->M2^ || |+--M3<-+
客戶端發起了一個插入語句給M1,M1執行了之后,寫入了M1的binlog文件中,包括了server id為1.這個事件被發給了M2,M2也執行了這個語句,然后寫binlog的時候,server id還是1,因為這個事件最初是由M1發起的.然后M3也收到了這個事件,執行完成后寫入到M3的binlog文件時,server id還是1.然后M1收到了這個事件之后,在執行插入語句之前,可以分析出server id=1,也就是這個語句最初是本機發起的,這個語句會被忽略執行.
event_length
4字節.事件的總長度,包括事件頭和事件數據.大部分的事件小于1000字節,除非使用LOAD DATA INFILE(因為包括加載文件,所以他們可能很大)
next_position(v1不包括):4字節.下個時間在master的binlog中的位置.這個格式在binlog和relay log中不一樣,而且與server版本有關(對于relay log來說,與master的版本有關)
v3版本的binlog:事件開頭的偏移量,從binlog文件的開頭開始計算.也便是說,在事件寫入之前,等于tell()的值. 所以binlog的第一個事件的next_position=4,對于事件n和n+1,next_position(n+1)=next_position(n)+event_length(n).
v3版本的relay log,master是v1:可能是0,但是沒法測試,因為現在已經基本沒有3.23的服務器了.
v3版本的relay log,master是v3:開頭變亂的偏移量和master中binlog文件一樣,也是從master的binlog文件開頭開始計算.
v4版本的binlog:事件結尾的偏移量,從binlog文件開頭開始計算.也便是說,等于在事件被寫入之后,正好等于tell()的值.所以binlog中第一個事件的next_position=4+event_length,對于事件n和n+1,next_position(n+1)=next_position(n)+event_length(n+1).
flags(v1中沒有)
2字節,詳見下一節.
extra_headers(v1和v3中不存在)
可變大小,當前為0.
變亂flag
對于v3及以上版本中,事件頭中包括一個2字節的時間flag在FLAGS_OFFSET=17位置上.在log_event.h中并沒有定義.
當前的變亂flag:
LOG_EVENT_BINLOG_IN_USE_F=0x1(5.0.3新增)
表示一個binlog文件是否正確的被關閉了.這個標志位只對FORMAT_DESCRIPTION_EVENT生效.當這個變亂被寫入日志文件時,才會設置這個標志位.當日志文件后續被關閉后,這個標志位會被清除掉.(這是Mysql修改已經寫完的binlog文件的唯一情況).
LOG_EVENT_THREAD_SPECIFIC_F=0x4(4.1.0新增)
僅供mysqlbinlog使用,使他能夠正確的處理臨時表.mysqlbinlog把binlog中的事件打印出來,讓你能夠理解打印出來的內容.但是如果兩個獨立的線程使用同樣的臨時表名,好比:
<thread id 1>CREATE TEMPORARY TABLE t (a INT);<thread id 2>CREATE TEMPORARY TABLE t (a INT);
這種情況下,簡單的執行sql語句,會導致表t已經存在的錯誤.所以使用臨時表的事件必要設置這個標志位,那樣mysqlbinlog知道必要在變量值錢設置假的線程id,例如:
SET PSEUDO_THREAD_ID=1;CREATE TEMPORARY TABLE t (a INT);SET PSEUDO_THREAD_ID=2;CREATE TEMPORARY TABLE t (a INT);
這樣,服務器接收到命令后就沒有歧義了.所有情況下都打印SET PSEUDO_THREAD_ID,及時臨時表沒有用到,這樣不會產生bug,但是會有點慢.
LOG_EVENT_SUPPRESS_USE_F=0x8(4.1.7新增)
在一個語句被記錄前,抑制產生USE語句.用于任何不需要使用默認數據庫的事件中,好比CREATE DATABASE和DROP DATABASE.
LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F=0x10(5.1.4新增)
在變亂寫入日志文件中后,導致binlog內部的表映射版本增加.
過時的標志位:
LOG_EVENT_TIME_F(4.1.1過期).從未被設置過
LOG_EVENT_FORCED_ROTATE_F(4.1.1過期):這個標志位是在master的ROTATE_EVENT中配置的,但是沒有任何用處.
三、變亂數據字段(變亂詳細信息)
變亂數據部分的結構依賴于變亂類型:
v1和v3版本中,變亂類型完全決定了數據格式
v4中,數據部分的解析除了依賴于事件類型,還依賴于格式描述事件的信息.這是因為在v4中,允許包括一個extra headers字段,這個字段的大小是在格式描述事件中定義的.實際上,當前這個字段是空的.
數據部分包括固定大小和可變大小兩部分.兩部分都可以為空,這由事件類型決定.(比如,STOP_EVENT只包括頭,數據內容都為空).
變亂數據的大小=變亂大小-變亂頭大小.下面的規則對binlog中所有的變亂都通用:
對于所有相同類型的變亂,固定部分的大小一樣.
對于所有相同類型的變亂,可變部分的大小可能不一樣.
歡迎參與《Mysql Binlog事件結構》討論,分享您的想法,維易PHP學院為您提供專業教程。
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/7885.html