binlog2sql UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 0: invalid start ...

問題場景

最近在使用binlog2sql進行MySQL數(shù)據(jù)庫誤操作恢復(fù)的時候莹汤,遇到了一個錯誤:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 0: invalid start byte

原因

通過檢查源碼和測試發(fā)現(xiàn)罩缴,這個問題是由于源代碼中溢陪,在生成回滾語句時,首先將回滾語句保存到臨時文件中盯孙,然后按照block讀取臨時文件羽利,倒序輸出語句。
最后生成的回滾語句和原始的執(zhí)行順序是相反的序苏,即后執(zhí)行的語句先回滾手幢。
在Python3環(huán)境中,需要使用utf-8對文件內(nèi)容進行解碼忱详,在解碼時围来,如果一個block的內(nèi)容是以b開頭的,就會出現(xiàn)解碼失敗報錯的情況。

處理方案

要修復(fù)這個問題监透,可以更新代碼的以下部分
也可以直接下載更新后的代碼 binlog2sql

    def print_rollback_sql(self, filename):
        """print rollback sql from tmp_file"""
        # 首先嘗試原始方法
        try:
            with open(filename, "rb") as f_tmp:
                batch_size = 1000
                i = 0
                for line in reversed_lines(f_tmp):
                    print(line.rstrip())
                    if i >= batch_size:
                        i = 0
                        if self.back_interval:
                            print('SELECT SLEEP(%s);' % self.back_interval)
                    else:
                        i += 1
        # 如果使用原始方法遇到問題桶错,讀取整個文件進行倒序輸出
        # 占用內(nèi)存可能上升
        except:
            with open(filename, "rb") as f_tmp:
                s = f_tmp.read()
                if sys.version > '3':
                    s_decode = s.decode("utf-8")
            s_list = s_decode.split("\n")
            s_list.reverse()
            batch_size = 1000
            i = 0
            for line in s_list:
                print(line.rstrip())
                if i >= batch_size:
                    i = 0
                    if self.back_interval:
                        print('SELECT SLEEP(%s);' % self.back_interval)
                    else:
                        i += 1

binlog2sql 說明

從MySQL binlog解析出你要的SQL。根據(jù)不同選項胀蛮,你可以得到原始SQL院刁、回滾SQL、去除主鍵的INSERT SQL等粪狼。

用途

  • 數(shù)據(jù)快速回滾(閃回)
  • 主從切換后新master丟數(shù)據(jù)的修復(fù)
  • 從binlog生成標(biāo)準(zhǔn)SQL黎比,帶來的衍生功能

環(huán)境

* Python 2.7, 3.4+
* MySQL 5.6, 5.7

安裝

shell> git clone https://github.com/danfengcao/binlog2sql.git && cd binlog2sql
shell> pip install -r requirements.txt

使用

MySQL server必須設(shè)置以下參數(shù):

[mysqld]
server_id = 1
log_bin = /var/log/mysql/mysql-bin.log
max_binlog_size = 1G
binlog_format = row
binlog_row_image = full

user需要的最小權(quán)限集合:

select, super/replication client, replication slave

建議授權(quán)
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 

權(quán)限說明

  • select:需要讀取server端information_schema.COLUMNS表,獲取表結(jié)構(gòu)的元信息鸳玩,拼接成可視化的sql語句
  • super/replication client:兩個權(quán)限都可以阅虫,需要執(zhí)行'SHOW MASTER STATUS', 獲取server端的binlog列表
  • replication slave:通過BINLOG_DUMP協(xié)議獲取binlog內(nèi)容的權(quán)限

基本用法

解析出標(biāo)準(zhǔn)SQL

shell> python binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -t test3 test4 --start-file='mysql-bin.000002'

輸出:
INSERT INTO `test`.`test3`(`addtime`, `data`, `id`) VALUES ('2016-12-10 13:03:38', 'english', 4); #start 570 end 736
UPDATE `test`.`test3` SET `addtime`='2016-12-10 12:00:00', `data`='中文', `id`=3 WHERE `addtime`='2016-12-10 13:03:22' AND `data`='中文' AND `id`=3 LIMIT 1; #start 763 end 954
DELETE FROM `test`.`test3` WHERE `addtime`='2016-12-10 13:03:38' AND `data`='english' AND `id`=4 LIMIT 1; #start 981 end 1147

解析出回滾SQL


shell> python binlog2sql.py --flashback -h127.0.0.1 -P3306 -uadmin -p'admin' -dtest -ttest3 --start-file='mysql-bin.000002' --start-position=763 --stop-position=1147

輸出:
INSERT INTO `test`.`test3`(`addtime`, `data`, `id`) VALUES ('2016-12-10 13:03:38', 'english', 4); #start 981 end 1147
UPDATE `test`.`test3` SET `addtime`='2016-12-10 13:03:22', `data`='中文', `id`=3 WHERE `addtime`='2016-12-10 12:00:00' AND `data`='中文' AND `id`=3 LIMIT 1; #start 763 end 954

選項

mysql連接配置

-h host; -P port; -u user; -p password

解析模式

--stop-never 持續(xù)解析binlog〔桓可選颓帝。默認(rèn)False,同步至執(zhí)行命令時最新的binlog位置窝革。

-K, --no-primary-key 對INSERT語句去除主鍵购城。可選虐译。默認(rèn)False

-B, --flashback 生成回滾SQL瘪板,可解析大文件,不受內(nèi)存限制漆诽∥昱剩可選。默認(rèn)False厢拭。與stop-never或no-primary-key不能同時添加兰英。

--back-interval -B模式下,每打印一千行回滾SQL供鸠,加一句SLEEP多少秒畦贸,如不想加SLEEP,請設(shè)為0楞捂”』担可選。默認(rèn)1.0寨闹。

解析范圍控制

--start-file 起始解析文件胶坠,只需文件名,無需全路徑 鼻忠。必須涵但。

--start-position/--start-pos 起始解析位置杈绸。可選矮瘟。默認(rèn)為start-file的起始位置瞳脓。

--stop-file/--end-file 終止解析文件〕合溃可選劫侧。默認(rèn)為start-file同一個文件。若解析模式為stop-never哨啃,此選項失效烧栋。

--stop-position/--end-pos 終止解析位置∪颍可選审姓。默認(rèn)為stop-file的最末位置;若解析模式為stop-never祝峻,此選項失效魔吐。

--start-datetime 起始解析時間,格式'%Y-%m-%d %H:%M:%S'莱找〕昴罚可選。默認(rèn)不過濾奥溺。

--stop-datetime 終止解析時間辞色,格式'%Y-%m-%d %H:%M:%S'「《ǎ可選相满。默認(rèn)不過濾。

對象過濾

-d, --databases 只解析目標(biāo)db的sql壶唤,多個庫用空格隔開雳灵,如-d db1 db2≌⒖可選。默認(rèn)為空琳省。

-t, --tables 只解析目標(biāo)table的sql迎吵,多張表用空格隔開,如-t tbl1 tbl2针贬』鞣眩可選。默認(rèn)為空桦他。

--only-dml 只解析dml蔫巩,忽略ddl。可選圆仔。默認(rèn)False垃瞧。

--sql-type 只解析指定類型,支持INSERT, UPDATE, DELETE坪郭。多個類型用空格隔開个从,如--sql-type INSERT DELETE⊥嵛郑可選嗦锐。默認(rèn)為增刪改都解析。用了此參數(shù)但沒填任何類型沪曙,則三者都不解析奕污。

--trans-number 解析的事務(wù)數(shù)量,可選液走。默認(rèn)無限制 這個是我個人修改后代碼中的功能碳默,源代碼是沒有的

參考鏈接

源碼地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市育灸,隨后出現(xiàn)的幾起案子腻窒,更是在濱河造成了極大的恐慌,老刑警劉巖磅崭,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件儿子,死亡現(xiàn)場離奇詭異,居然都是意外死亡砸喻,警方通過查閱死者的電腦和手機柔逼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來割岛,“玉大人愉适,你說我怎么就攤上這事⊙⑵幔” “怎么了维咸?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長惠爽。 經(jīng)常有香客問我癌蓖,道長,這世上最難降的妖魔是什么婚肆? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任租副,我火速辦了婚禮,結(jié)果婚禮上较性,老公的妹妹穿的比我還像新娘用僧。我一直安慰自己结胀,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布责循。 她就那樣靜靜地躺著糟港,像睡著了一般。 火紅的嫁衣襯著肌膚如雪沼死。 梳的紋絲不亂的頭發(fā)上着逐,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天,我揣著相機與錄音意蛀,去河邊找鬼耸别。 笑死,一個胖子當(dāng)著我的面吹牛县钥,可吹牛的內(nèi)容都是我干的秀姐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼若贮,長吁一口氣:“原來是場噩夢啊……” “哼省有!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起谴麦,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蠢沿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后匾效,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舷蟀,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年面哼,在試婚紗的時候發(fā)現(xiàn)自己被綠了野宜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡魔策,死狀恐怖匈子,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情闯袒,我是刑警寧澤虎敦,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站政敢,受9級特大地震影響原茅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜堕仔,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望晌区。 院中可真熱鬧摩骨,春花似錦通贞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至灾馒,卻和暖如春茎用,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背睬罗。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工轨功, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人容达。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓古涧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親花盐。 傳聞我的和親對象是個殘疾皇子羡滑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,585評論 2 359