日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql格式分隔符row_MySQLRow格式Binlog的解析(1)

發(fā)布時間:2023/12/10 数据库 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql格式分隔符row_MySQLRow格式Binlog的解析(1) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

用MySQL 行格式的復制的Slave經(jīng)常會遇到復制出錯1062和1032 錯誤,一般是鏡像異常宕機導致主從復制數(shù)據(jù)不一致所致,但是有些庫本身很大,重建成本很大,并且這些庫的數(shù)據(jù)一致性用戶可能都不是太關(guān)心的,所以之前的處理辦法一般是遇到主鍵沖突的就跳過,遇到找不到key的就用mysqlbinlog解析一下 把數(shù)據(jù)補出來,但是這種方法太人肉話,處理起來很慢,所以之前做過一個自動修數(shù)據(jù)的工具,也是解析binlog日志,然后生成SQL語句去執(zhí)行。

做這個工具還有另外一個用途,既然能解析BINLOG日志,這樣也可以做基于BINLOG的恢復,當然這個功能之前阿里也有人做過,但是做的方法不太一樣,可以參考MySQL的 flashback.

解析BINLOG需要知道一下幾點:出現(xiàn)異常的start-position

異常結(jié)束的end-position

因為是在Slave機器上運行,所以這里解析的全部都是relay log.

通過show slave status 可以清楚的知道start-psoition: Relay_Log_Pos

end-position : 這個信息并不能直接從show slave status 里面獲得,這個要算一下,計算方法:

end-position = Relay_Log_Pos + (end_log_pos - Exec_Master_Log_Pos)

(end_log_pos - Exec_Master_Log_Pos) 這個就代表這個事物從開始到出錯執(zhí)行的字節(jié)數(shù)。

end_log_pos 在show slave status 的錯誤信息里面也有,取出來就可以了。

知道了起始位置和結(jié)束位置,剩下的就可以解析了。如果不清楚binlog event的可以看下官方文檔:

http://dev.mysql.com/doc/internals/en/binlog-event.html

寫代碼的過程中也大量參考了文檔。

我使用python進行解析的,其實用什么語言都一樣,步驟如下:

首先seek到起始位置

解析第一個event type ,如果是table_map_event 開啟解析,如果不是就跳過,因為如果是一個正常的語句在ROW格式里記錄的方式肯定是table_map_event + 具體的操作,所以如果第一個不是table_map_event 那么要么就是binlog有損壞 要么就是起始位置不對。

如果解析到了tabl_map_event,下面對我們有用的event類型也就三個:insert event / update event /delete event, 當解析掉這個event 我們基本上就可以拼湊出一個SQL語句了。

然后繼續(xù)解析下一個table_map_evnt 以此類推,就能解析出很多個SQL語句。

基本過程就是這樣,那么怎么解析呢

首先說說event:

基本上所有的event 格式都是一樣的,都是由header + data 這兩部分組成。

header 里面都是固定的,不同的event可變部分在DATA里面。

DATA分為fixed part 和variable part.

header 格式

| timestamp(0:4)| type_code(4:1)| server_id(5:4)| event_length(9:4)| next_position(13:4) | flags(17:2)| extra_header(19:x-19)|

data 格式

|fix_data x:y | variable_data

header 說明 :timestamp 時間戳

type_code event類型 很有用

server_id 沒啥用

event_lenght 整個event長度包括header

next_position 下個event的position 很有用

flags 沒用

extra_header 這個目前都沒啥用

所以整個header一共19字節(jié),DATA部分占用字節(jié)數(shù):event_length - 19

下面說一下幾種用到的BINLOG格式:TABLE_MAP_EVENT: 19

WRITE_ROWS_EVENT : 23

UPDATE_ROWS_EVENT : 24

DELETE_ROWS_EVENT : 25

這里要注意一下,從MySQL5.6.2 開始 event的type 變化了,所以導5.6的需要改一下,5.6的我還沒有詳細的測試過,不知道還有什么坑。#mysql5.6.2 events

# WRITE_ROWS_EVENT= 30

# UPDATE_ROWS_EVENT= 31

# DELETE_ROWS_EVENT= 32

# INCIDENT_EVENT= 26

因為header部分都一樣,所以直接說DATA部分了。

TABLE_MAP_EVENT:

Data:

Fixed data:Table_id (6bytes)

extra not use (2bytes)

Variable dataSchema_length (1bytes)

Schame name (Schema_length size )

0 //空字符占一字節(jié)

Table length (1bytes)

Table name (table length size)

0 //空字符占一字節(jié)

Column size (變長,最多存8個byte,最大為2的64次方)

Coulmn type (column size bytes )

我們能從table_map_event 里面得到什么?

沒錯 主要能得到的就是庫名和表名還有字段類型

表明和庫名都好弄,直接讀出來不用轉(zhuǎn),字段類型MySQL還有一個專門的轉(zhuǎn)換表,每一個字節(jié)對應(yīng)一個字段類型。

http://dev.mysql.com/doc/internals/en/com-query-response.html#packet-Protocol::MYSQL_TYPE_DATETIME

那么現(xiàn)在表表庫名字段類型都有了,感覺還少了字段名稱,字段名稱直接去MySQL里面去查。

sql= ("select * from information_schema.columns where table_schema='

%s’"

" and table_name='%s’")

這樣我們這些元數(shù)據(jù)信息都有了,就需要解析具體的數(shù)據(jù)了,然后把解析好的數(shù)據(jù)直接填進去。

那么下面就只剩下如何解析別的event格式了。

先從WRITE_ROWS_EVENT 開始:

WRITE_ROWS_EVENT 其實就是一個insert操作,前面也說過每一份event的header都是一樣的,只是DATA部分有區(qū)分而已,所以WRITE_ROWS_EVENT也一樣,header部分為19字節(jié),DATA部門為event_length-19字節(jié)。

那么DATA部分中的fixed data 和variables data各是什么呢?

Fixed data :

Table_id (6bytes)

extra not use (2bytes)

Variables data :col_num (dynamic),一般是1bytes.

map_col (table bitmap)

Record

可以看到fixed data 部分有用的信息不多,可能table_id 還有些用,重要的在variables data 部分。col_num 代表字段的個數(shù)占用字節(jié)數(shù)是可變的,一般一字節(jié)就夠了,1字節(jié)/2的八次方 一般也很難有表有幾百個字段。

map_col 這個代表字段是否為空

Record 這個就是具體的記錄內(nèi)容。

怎么解析Record?

Record的格式是bit_map + record 的結(jié)構(gòu)。

bit_map 的每一位代表字段是否為空,所以bit_map占用的字節(jié)數(shù)為:((columns+7)/8)

比如1100 代表一共四個字段,前兩個字段為非空,后兩個為NULL,為NULL的數(shù)據(jù)在record里面是不記錄的。

所以呢,首先根據(jù)bitmap 判斷字段是否為空,如果不為空則拿程序繼續(xù)往下掃描,如果為空則判斷下一個字段是否為空。

至此一個insert語句基本上是解析完了。

除此之外DELETE_ROWS_EVENT 基本上和insert一樣。

UPDATE_ROWS_EVENT 稍微有一點點特別,UPDATE_ROWS_EVENT 也是bitmap + record ,但是Update包含更新前像和后像,所以一條Update的格式為

bitmap + record (前像) + bitnap + record (后像)

基本上簡單的一條語句就是這樣:

table-map-event + insert/update/delete event

那么可能會出現(xiàn)這樣的情況比如:

insert values (),(),() 或者delete id in (…)

一條SQL操作很多條記錄的情況。

那么這種record 的格式就變成 record = (bitmap + data) + (bitmap + data) .. 直到解析完為止

所以掃描的時候一定要把這個event掃描完,不然很容易出錯。

這里先簡單的介紹一下如何解析BINLOG吧,下面會再詳細解析如何解析各個不同類型的字段。

本條技術(shù)文章來源于互聯(lián)網(wǎng),如果無意侵犯您的權(quán)益請點擊此處反饋版權(quán)投訴

本文系統(tǒng)來源:php中文網(wǎng)

總結(jié)

以上是生活随笔為你收集整理的mysql格式分隔符row_MySQLRow格式Binlog的解析(1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。