MyFlash——美團點評的開源MySQL閃回工具

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

MyFlash——美團點評的開源MySQL閃回工具

每個event都是由event header 和event data組成。下面簡單介紹下幾種常見的binlog event。

① formart description event

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

MyFlash——美團點評的開源MySQL閃回工具

每個event都是由event header 和event data組成。下面簡單介紹下幾種常見的binlog event。

① formart description event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

170905 01:59:33 server id 10 end_log_pos 123 CRC32 0xed1ec563Start: binlog v 4, server v 5.7.18-log created 170905 01:59:33

② table map event

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

MyFlash——美團點評的開源MySQL閃回工具

每個event都是由event header 和event data組成。下面簡單介紹下幾種常見的binlog event。

① formart description event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

170905 01:59:33 server id 10 end_log_pos 123 CRC32 0xed1ec563Start: binlog v 4, server v 5.7.18-log created 170905 01:59:33

② table map event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 339 CRC32 0x3de40c0d  Table_map: `test`.`test4` mapped to number 238

③ update row event

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

MyFlash——美團點評的開源MySQL閃回工具

每個event都是由event header 和event data組成。下面簡單介紹下幾種常見的binlog event。

① formart description event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

170905 01:59:33 server id 10 end_log_pos 123 CRC32 0xed1ec563Start: binlog v 4, server v 5.7.18-log created 170905 01:59:33

② table map event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 339 CRC32 0x3de40c0d  Table_map: `test`.`test4` mapped to number 238

③ update row event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 385 CRC32 0x179ef6dd  Update_rows: table id 238 flags: STMT_END_F UPDATE `test`.`test4` WHERE @1=3 SET @1=13;

binlog event回滾

根據上面的binlog介紹,可以看到每個binlog event中event header有個type_code,其中insert為30,update為31,delete為32。對於insert和delete兩個相反的操作,只需把type_code互換,則在binlog event級別完成回滾。

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

MyFlash——美團點評的開源MySQL閃回工具

每個event都是由event header 和event data組成。下面簡單介紹下幾種常見的binlog event。

① formart description event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

170905 01:59:33 server id 10 end_log_pos 123 CRC32 0xed1ec563Start: binlog v 4, server v 5.7.18-log created 170905 01:59:33

② table map event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 339 CRC32 0x3de40c0d  Table_map: `test`.`test4` mapped to number 238

③ update row event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 385 CRC32 0x179ef6dd  Update_rows: table id 238 flags: STMT_END_F UPDATE `test`.`test4` WHERE @1=3 SET @1=13;

binlog event回滾

根據上面的binlog介紹,可以看到每個binlog event中event header有個type_code,其中insert為30,update為31,delete為32。對於insert和delete兩個相反的操作,只需把type_code互換,則在binlog event級別完成回滾。

MyFlash——美團點評的開源MySQL閃回工具

而對於update操作,其格式如下。

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

MyFlash——美團點評的開源MySQL閃回工具

每個event都是由event header 和event data組成。下面簡單介紹下幾種常見的binlog event。

① formart description event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

170905 01:59:33 server id 10 end_log_pos 123 CRC32 0xed1ec563Start: binlog v 4, server v 5.7.18-log created 170905 01:59:33

② table map event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 339 CRC32 0x3de40c0d  Table_map: `test`.`test4` mapped to number 238

③ update row event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 385 CRC32 0x179ef6dd  Update_rows: table id 238 flags: STMT_END_F UPDATE `test`.`test4` WHERE @1=3 SET @1=13;

binlog event回滾

根據上面的binlog介紹,可以看到每個binlog event中event header有個type_code,其中insert為30,update為31,delete為32。對於insert和delete兩個相反的操作,只需把type_code互換,則在binlog event級別完成回滾。

MyFlash——美團點評的開源MySQL閃回工具

而對於update操作,其格式如下。

MyFlash——美團點評的開源MySQL閃回工具

其中,BI是指before image,AI是指after image。

我們只需依次遍歷修改前的數據和修改後的數據,並一一互換即可。因此整個回滾操作的難點在於回滾update語句,而update語句回滾的核心在於計算出每個AI、BI的長度。下面介紹下長度以及部分字段的計算方法。

鏡像長度計算

鏡像是由一個個字段組成的,根據字段類型的不同,其計算長度的方法也不一樣。

  • 只與字段類型相關。比如int佔用4個字節,bingint佔用8個字節。其中類型信息可以從table map event中獲取。

  • 與字段類型及其參數相關。比如decimal(18,9),佔用9個字節,參數信息在table map event中。

  • 與字段類型、參數以及實際存儲的值相關。比如varchar(10),有1個字節表示長度,之後的字節才表示真正的數據。比如varchar(280),有2個字節表示長度。實際的長度和數據在一起。

解析binlog中的若干個關鍵點

① length encoded integer

binlog中一個或者多個字節組合,分別表示了不同的含義。比如,timestamp是由固定的4個字節組成,event類型由一個字節表示;數據庫名和表名最長為64個字符,即使每個字符佔用3個字節,那麼佔用的字節數為192<255。因此最多使用一個字節,就可以完成實際長度表示。

然而列的實際數量,可能需要超過1個字節、2個字節、3個字節甚至8個字節去表示。如果我們使用最大的8個字節去表示,那麼在絕大多數情況下都是浪費存儲空間的。針對這種情況,length encoded integer應運而生。

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

MyFlash——美團點評的開源MySQL閃回工具

每個event都是由event header 和event data組成。下面簡單介紹下幾種常見的binlog event。

① formart description event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

170905 01:59:33 server id 10 end_log_pos 123 CRC32 0xed1ec563Start: binlog v 4, server v 5.7.18-log created 170905 01:59:33

② table map event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 339 CRC32 0x3de40c0d  Table_map: `test`.`test4` mapped to number 238

③ update row event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 385 CRC32 0x179ef6dd  Update_rows: table id 238 flags: STMT_END_F UPDATE `test`.`test4` WHERE @1=3 SET @1=13;

binlog event回滾

根據上面的binlog介紹,可以看到每個binlog event中event header有個type_code,其中insert為30,update為31,delete為32。對於insert和delete兩個相反的操作,只需把type_code互換,則在binlog event級別完成回滾。

MyFlash——美團點評的開源MySQL閃回工具

而對於update操作,其格式如下。

MyFlash——美團點評的開源MySQL閃回工具

其中,BI是指before image,AI是指after image。

我們只需依次遍歷修改前的數據和修改後的數據,並一一互換即可。因此整個回滾操作的難點在於回滾update語句,而update語句回滾的核心在於計算出每個AI、BI的長度。下面介紹下長度以及部分字段的計算方法。

鏡像長度計算

鏡像是由一個個字段組成的,根據字段類型的不同,其計算長度的方法也不一樣。

  • 只與字段類型相關。比如int佔用4個字節,bingint佔用8個字節。其中類型信息可以從table map event中獲取。

  • 與字段類型及其參數相關。比如decimal(18,9),佔用9個字節,參數信息在table map event中。

  • 與字段類型、參數以及實際存儲的值相關。比如varchar(10),有1個字節表示長度,之後的字節才表示真正的數據。比如varchar(280),有2個字節表示長度。實際的長度和數據在一起。

解析binlog中的若干個關鍵點

① length encoded integer

binlog中一個或者多個字節組合,分別表示了不同的含義。比如,timestamp是由固定的4個字節組成,event類型由一個字節表示;數據庫名和表名最長為64個字符,即使每個字符佔用3個字節,那麼佔用的字節數為192<255。因此最多使用一個字節,就可以完成實際長度表示。

然而列的實際數量,可能需要超過1個字節、2個字節、3個字節甚至8個字節去表示。如果我們使用最大的8個字節去表示,那麼在絕大多數情況下都是浪費存儲空間的。針對這種情況,length encoded integer應運而生。

MyFlash——美團點評的開源MySQL閃回工具

比如在獲取一個varchar類型的長度時,首先讀取第一個字節,如果值小於251,那麼varchar的長度就是第一個字節表示的長度。如果第一個字節的值為0xFC,那麼varchar的長度是由該字節之後的後兩個字節組成,以此類推。

② decimal類型

decimal是由整數部分和小數部分組成。無論是整數還是小數,每9個數字,需要4個字節。如果不是9的倍數,剩餘的小數位,需要的字節數如下,為方便描述,將該關係定義為函數Fnum。

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

MyFlash——美團點評的開源MySQL閃回工具

每個event都是由event header 和event data組成。下面簡單介紹下幾種常見的binlog event。

① formart description event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

170905 01:59:33 server id 10 end_log_pos 123 CRC32 0xed1ec563Start: binlog v 4, server v 5.7.18-log created 170905 01:59:33

② table map event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 339 CRC32 0x3de40c0d  Table_map: `test`.`test4` mapped to number 238

③ update row event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 385 CRC32 0x179ef6dd  Update_rows: table id 238 flags: STMT_END_F UPDATE `test`.`test4` WHERE @1=3 SET @1=13;

binlog event回滾

根據上面的binlog介紹,可以看到每個binlog event中event header有個type_code,其中insert為30,update為31,delete為32。對於insert和delete兩個相反的操作,只需把type_code互換,則在binlog event級別完成回滾。

MyFlash——美團點評的開源MySQL閃回工具

而對於update操作,其格式如下。

MyFlash——美團點評的開源MySQL閃回工具

其中,BI是指before image,AI是指after image。

我們只需依次遍歷修改前的數據和修改後的數據,並一一互換即可。因此整個回滾操作的難點在於回滾update語句,而update語句回滾的核心在於計算出每個AI、BI的長度。下面介紹下長度以及部分字段的計算方法。

鏡像長度計算

鏡像是由一個個字段組成的,根據字段類型的不同,其計算長度的方法也不一樣。

  • 只與字段類型相關。比如int佔用4個字節,bingint佔用8個字節。其中類型信息可以從table map event中獲取。

  • 與字段類型及其參數相關。比如decimal(18,9),佔用9個字節,參數信息在table map event中。

  • 與字段類型、參數以及實際存儲的值相關。比如varchar(10),有1個字節表示長度,之後的字節才表示真正的數據。比如varchar(280),有2個字節表示長度。實際的長度和數據在一起。

解析binlog中的若干個關鍵點

① length encoded integer

binlog中一個或者多個字節組合,分別表示了不同的含義。比如,timestamp是由固定的4個字節組成,event類型由一個字節表示;數據庫名和表名最長為64個字符,即使每個字符佔用3個字節,那麼佔用的字節數為192<255。因此最多使用一個字節,就可以完成實際長度表示。

然而列的實際數量,可能需要超過1個字節、2個字節、3個字節甚至8個字節去表示。如果我們使用最大的8個字節去表示,那麼在絕大多數情況下都是浪費存儲空間的。針對這種情況,length encoded integer應運而生。

MyFlash——美團點評的開源MySQL閃回工具

比如在獲取一個varchar類型的長度時,首先讀取第一個字節,如果值小於251,那麼varchar的長度就是第一個字節表示的長度。如果第一個字節的值為0xFC,那麼varchar的長度是由該字節之後的後兩個字節組成,以此類推。

② decimal類型

decimal是由整數部分和小數部分組成。無論是整數還是小數,每9個數字,需要4個字節。如果不是9的倍數,剩餘的小數位,需要的字節數如下,為方便描述,將該關係定義為函數Fnum。

MyFlash——美團點評的開源MySQL閃回工具

舉例,對於 decimal(18,10):

  1. 整數部分可展示的為8,用int,即4個字節。

  2. 小數部分,需要的字節數為 (10 /9)*4+Fnum(10%9)=5。

  3. 那麼總共加起來需要4+5=9個字節。

閃回工具架構

在上面的章節中,介紹了單個binlog event的反轉方法。在實踐中,我們往往需要把某個binlog,按照指定的條件,過濾出需要的binlog,並進行反轉。那麼MyFlash是如何完成這些目標的呢?

解析binlog

首先把binlog文件,解析成多個event,放入到相關隊列中。在實現上,為了儘可能加快解析速度,可以讓用戶指定解析的開始與結束位置。把binlog文件解析成binlog event後,再判斷下是否符合指定的時間條件,若不符合,則丟棄該event。

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

MyFlash——美團點評的開源MySQL閃回工具

每個event都是由event header 和event data組成。下面簡單介紹下幾種常見的binlog event。

① formart description event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

170905 01:59:33 server id 10 end_log_pos 123 CRC32 0xed1ec563Start: binlog v 4, server v 5.7.18-log created 170905 01:59:33

② table map event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 339 CRC32 0x3de40c0d  Table_map: `test`.`test4` mapped to number 238

③ update row event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 385 CRC32 0x179ef6dd  Update_rows: table id 238 flags: STMT_END_F UPDATE `test`.`test4` WHERE @1=3 SET @1=13;

binlog event回滾

根據上面的binlog介紹,可以看到每個binlog event中event header有個type_code,其中insert為30,update為31,delete為32。對於insert和delete兩個相反的操作,只需把type_code互換,則在binlog event級別完成回滾。

MyFlash——美團點評的開源MySQL閃回工具

而對於update操作,其格式如下。

MyFlash——美團點評的開源MySQL閃回工具

其中,BI是指before image,AI是指after image。

我們只需依次遍歷修改前的數據和修改後的數據,並一一互換即可。因此整個回滾操作的難點在於回滾update語句,而update語句回滾的核心在於計算出每個AI、BI的長度。下面介紹下長度以及部分字段的計算方法。

鏡像長度計算

鏡像是由一個個字段組成的,根據字段類型的不同,其計算長度的方法也不一樣。

  • 只與字段類型相關。比如int佔用4個字節,bingint佔用8個字節。其中類型信息可以從table map event中獲取。

  • 與字段類型及其參數相關。比如decimal(18,9),佔用9個字節,參數信息在table map event中。

  • 與字段類型、參數以及實際存儲的值相關。比如varchar(10),有1個字節表示長度,之後的字節才表示真正的數據。比如varchar(280),有2個字節表示長度。實際的長度和數據在一起。

解析binlog中的若干個關鍵點

① length encoded integer

binlog中一個或者多個字節組合,分別表示了不同的含義。比如,timestamp是由固定的4個字節組成,event類型由一個字節表示;數據庫名和表名最長為64個字符,即使每個字符佔用3個字節,那麼佔用的字節數為192<255。因此最多使用一個字節,就可以完成實際長度表示。

然而列的實際數量,可能需要超過1個字節、2個字節、3個字節甚至8個字節去表示。如果我們使用最大的8個字節去表示,那麼在絕大多數情況下都是浪費存儲空間的。針對這種情況,length encoded integer應運而生。

MyFlash——美團點評的開源MySQL閃回工具

比如在獲取一個varchar類型的長度時,首先讀取第一個字節,如果值小於251,那麼varchar的長度就是第一個字節表示的長度。如果第一個字節的值為0xFC,那麼varchar的長度是由該字節之後的後兩個字節組成,以此類推。

② decimal類型

decimal是由整數部分和小數部分組成。無論是整數還是小數,每9個數字,需要4個字節。如果不是9的倍數,剩餘的小數位,需要的字節數如下,為方便描述,將該關係定義為函數Fnum。

MyFlash——美團點評的開源MySQL閃回工具

舉例,對於 decimal(18,10):

  1. 整數部分可展示的為8,用int,即4個字節。

  2. 小數部分,需要的字節數為 (10 /9)*4+Fnum(10%9)=5。

  3. 那麼總共加起來需要4+5=9個字節。

閃回工具架構

在上面的章節中,介紹了單個binlog event的反轉方法。在實踐中,我們往往需要把某個binlog,按照指定的條件,過濾出需要的binlog,並進行反轉。那麼MyFlash是如何完成這些目標的呢?

解析binlog

首先把binlog文件,解析成多個event,放入到相關隊列中。在實現上,為了儘可能加快解析速度,可以讓用戶指定解析的開始與結束位置。把binlog文件解析成binlog event後,再判斷下是否符合指定的時間條件,若不符合,則丟棄該event。

MyFlash——美團點評的開源MySQL閃回工具

注意:用戶可以不指定位置和時間,則解析整個文件。如果只指定時間,那麼也需要從文件開始處解析,取出時間信息,再進行判斷。因此,當需要回滾的binlog只佔整個binlog的一小部分時,推薦使用指定位置。

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

MyFlash——美團點評的開源MySQL閃回工具

每個event都是由event header 和event data組成。下面簡單介紹下幾種常見的binlog event。

① formart description event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

170905 01:59:33 server id 10 end_log_pos 123 CRC32 0xed1ec563Start: binlog v 4, server v 5.7.18-log created 170905 01:59:33

② table map event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 339 CRC32 0x3de40c0d  Table_map: `test`.`test4` mapped to number 238

③ update row event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 385 CRC32 0x179ef6dd  Update_rows: table id 238 flags: STMT_END_F UPDATE `test`.`test4` WHERE @1=3 SET @1=13;

binlog event回滾

根據上面的binlog介紹,可以看到每個binlog event中event header有個type_code,其中insert為30,update為31,delete為32。對於insert和delete兩個相反的操作,只需把type_code互換,則在binlog event級別完成回滾。

MyFlash——美團點評的開源MySQL閃回工具

而對於update操作,其格式如下。

MyFlash——美團點評的開源MySQL閃回工具

其中,BI是指before image,AI是指after image。

我們只需依次遍歷修改前的數據和修改後的數據,並一一互換即可。因此整個回滾操作的難點在於回滾update語句,而update語句回滾的核心在於計算出每個AI、BI的長度。下面介紹下長度以及部分字段的計算方法。

鏡像長度計算

鏡像是由一個個字段組成的,根據字段類型的不同,其計算長度的方法也不一樣。

  • 只與字段類型相關。比如int佔用4個字節,bingint佔用8個字節。其中類型信息可以從table map event中獲取。

  • 與字段類型及其參數相關。比如decimal(18,9),佔用9個字節,參數信息在table map event中。

  • 與字段類型、參數以及實際存儲的值相關。比如varchar(10),有1個字節表示長度,之後的字節才表示真正的數據。比如varchar(280),有2個字節表示長度。實際的長度和數據在一起。

解析binlog中的若干個關鍵點

① length encoded integer

binlog中一個或者多個字節組合,分別表示了不同的含義。比如,timestamp是由固定的4個字節組成,event類型由一個字節表示;數據庫名和表名最長為64個字符,即使每個字符佔用3個字節,那麼佔用的字節數為192<255。因此最多使用一個字節,就可以完成實際長度表示。

然而列的實際數量,可能需要超過1個字節、2個字節、3個字節甚至8個字節去表示。如果我們使用最大的8個字節去表示,那麼在絕大多數情況下都是浪費存儲空間的。針對這種情況,length encoded integer應運而生。

MyFlash——美團點評的開源MySQL閃回工具

比如在獲取一個varchar類型的長度時,首先讀取第一個字節,如果值小於251,那麼varchar的長度就是第一個字節表示的長度。如果第一個字節的值為0xFC,那麼varchar的長度是由該字節之後的後兩個字節組成,以此類推。

② decimal類型

decimal是由整數部分和小數部分組成。無論是整數還是小數,每9個數字,需要4個字節。如果不是9的倍數,剩餘的小數位,需要的字節數如下,為方便描述,將該關係定義為函數Fnum。

MyFlash——美團點評的開源MySQL閃回工具

舉例,對於 decimal(18,10):

  1. 整數部分可展示的為8,用int,即4個字節。

  2. 小數部分,需要的字節數為 (10 /9)*4+Fnum(10%9)=5。

  3. 那麼總共加起來需要4+5=9個字節。

閃回工具架構

在上面的章節中,介紹了單個binlog event的反轉方法。在實踐中,我們往往需要把某個binlog,按照指定的條件,過濾出需要的binlog,並進行反轉。那麼MyFlash是如何完成這些目標的呢?

解析binlog

首先把binlog文件,解析成多個event,放入到相關隊列中。在實現上,為了儘可能加快解析速度,可以讓用戶指定解析的開始與結束位置。把binlog文件解析成binlog event後,再判斷下是否符合指定的時間條件,若不符合,則丟棄該event。

MyFlash——美團點評的開源MySQL閃回工具

注意:用戶可以不指定位置和時間,則解析整個文件。如果只指定時間,那麼也需要從文件開始處解析,取出時間信息,再進行判斷。因此,當需要回滾的binlog只佔整個binlog的一小部分時,推薦使用指定位置。

MyFlash——美團點評的開源MySQL閃回工具

重組event

把binlog event組成最小執行單元。在常見的binlog event中table_map event包含了所要了表名、庫名等元數據信息,而row_event(包含write_event、delete_event、update_event)包含了真正的數據。因此在設計中使用了一個最小執行單元概念。所謂的最小執行單元,即least execution event unit,通常包含一個table_map event和若干個row_event。

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

MyFlash——美團點評的開源MySQL閃回工具

每個event都是由event header 和event data組成。下面簡單介紹下幾種常見的binlog event。

① formart description event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

170905 01:59:33 server id 10 end_log_pos 123 CRC32 0xed1ec563Start: binlog v 4, server v 5.7.18-log created 170905 01:59:33

② table map event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 339 CRC32 0x3de40c0d  Table_map: `test`.`test4` mapped to number 238

③ update row event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 385 CRC32 0x179ef6dd  Update_rows: table id 238 flags: STMT_END_F UPDATE `test`.`test4` WHERE @1=3 SET @1=13;

binlog event回滾

根據上面的binlog介紹,可以看到每個binlog event中event header有個type_code,其中insert為30,update為31,delete為32。對於insert和delete兩個相反的操作,只需把type_code互換,則在binlog event級別完成回滾。

MyFlash——美團點評的開源MySQL閃回工具

而對於update操作,其格式如下。

MyFlash——美團點評的開源MySQL閃回工具

其中,BI是指before image,AI是指after image。

我們只需依次遍歷修改前的數據和修改後的數據,並一一互換即可。因此整個回滾操作的難點在於回滾update語句,而update語句回滾的核心在於計算出每個AI、BI的長度。下面介紹下長度以及部分字段的計算方法。

鏡像長度計算

鏡像是由一個個字段組成的,根據字段類型的不同,其計算長度的方法也不一樣。

  • 只與字段類型相關。比如int佔用4個字節,bingint佔用8個字節。其中類型信息可以從table map event中獲取。

  • 與字段類型及其參數相關。比如decimal(18,9),佔用9個字節,參數信息在table map event中。

  • 與字段類型、參數以及實際存儲的值相關。比如varchar(10),有1個字節表示長度,之後的字節才表示真正的數據。比如varchar(280),有2個字節表示長度。實際的長度和數據在一起。

解析binlog中的若干個關鍵點

① length encoded integer

binlog中一個或者多個字節組合,分別表示了不同的含義。比如,timestamp是由固定的4個字節組成,event類型由一個字節表示;數據庫名和表名最長為64個字符,即使每個字符佔用3個字節,那麼佔用的字節數為192<255。因此最多使用一個字節,就可以完成實際長度表示。

然而列的實際數量,可能需要超過1個字節、2個字節、3個字節甚至8個字節去表示。如果我們使用最大的8個字節去表示,那麼在絕大多數情況下都是浪費存儲空間的。針對這種情況,length encoded integer應運而生。

MyFlash——美團點評的開源MySQL閃回工具

比如在獲取一個varchar類型的長度時,首先讀取第一個字節,如果值小於251,那麼varchar的長度就是第一個字節表示的長度。如果第一個字節的值為0xFC,那麼varchar的長度是由該字節之後的後兩個字節組成,以此類推。

② decimal類型

decimal是由整數部分和小數部分組成。無論是整數還是小數,每9個數字,需要4個字節。如果不是9的倍數,剩餘的小數位,需要的字節數如下,為方便描述,將該關係定義為函數Fnum。

MyFlash——美團點評的開源MySQL閃回工具

舉例,對於 decimal(18,10):

  1. 整數部分可展示的為8,用int,即4個字節。

  2. 小數部分,需要的字節數為 (10 /9)*4+Fnum(10%9)=5。

  3. 那麼總共加起來需要4+5=9個字節。

閃回工具架構

在上面的章節中,介紹了單個binlog event的反轉方法。在實踐中,我們往往需要把某個binlog,按照指定的條件,過濾出需要的binlog,並進行反轉。那麼MyFlash是如何完成這些目標的呢?

解析binlog

首先把binlog文件,解析成多個event,放入到相關隊列中。在實現上,為了儘可能加快解析速度,可以讓用戶指定解析的開始與結束位置。把binlog文件解析成binlog event後,再判斷下是否符合指定的時間條件,若不符合,則丟棄該event。

MyFlash——美團點評的開源MySQL閃回工具

注意:用戶可以不指定位置和時間,則解析整個文件。如果只指定時間,那麼也需要從文件開始處解析,取出時間信息,再進行判斷。因此,當需要回滾的binlog只佔整個binlog的一小部分時,推薦使用指定位置。

MyFlash——美團點評的開源MySQL閃回工具

重組event

把binlog event組成最小執行單元。在常見的binlog event中table_map event包含了所要了表名、庫名等元數據信息,而row_event(包含write_event、delete_event、update_event)包含了真正的數據。因此在設計中使用了一個最小執行單元概念。所謂的最小執行單元,即least execution event unit,通常包含一個table_map event和若干個row_event。

MyFlash——美團點評的開源MySQL閃回工具

比如在binlog格式概覽一節中,介紹了table_map_event和update_row_event。如果只有update_row_event,那麼我們無法知道這個event對應的行記錄變更對應的表。因此一個完整的最小執行單元最少包含一個table_map_event和write_row_event、update_row_even、delete_row_event中的一個。

為什麼我們需要使用最小執行單元?因為我們在閃回操作時,不能簡單的把每個event反轉之後,然後再將所有event的順序反轉過來。如果這樣的話,就會出現table_map event在row event之後,這顯然是違反binlog執行邏輯的。

有了最小執行單元之後,只需兩步,即可完成反轉。

a. 反轉最小執行單元中的row event。

b. 逆序最小執行單元隊列,即可。

當然在反轉前,也可以增加過濾操作。比如過濾庫名、表名和SQL類型等。

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

MyFlash——美團點評的開源MySQL閃回工具

每個event都是由event header 和event data組成。下面簡單介紹下幾種常見的binlog event。

① formart description event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

170905 01:59:33 server id 10 end_log_pos 123 CRC32 0xed1ec563Start: binlog v 4, server v 5.7.18-log created 170905 01:59:33

② table map event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 339 CRC32 0x3de40c0d  Table_map: `test`.`test4` mapped to number 238

③ update row event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 385 CRC32 0x179ef6dd  Update_rows: table id 238 flags: STMT_END_F UPDATE `test`.`test4` WHERE @1=3 SET @1=13;

binlog event回滾

根據上面的binlog介紹,可以看到每個binlog event中event header有個type_code,其中insert為30,update為31,delete為32。對於insert和delete兩個相反的操作,只需把type_code互換,則在binlog event級別完成回滾。

MyFlash——美團點評的開源MySQL閃回工具

而對於update操作,其格式如下。

MyFlash——美團點評的開源MySQL閃回工具

其中,BI是指before image,AI是指after image。

我們只需依次遍歷修改前的數據和修改後的數據,並一一互換即可。因此整個回滾操作的難點在於回滾update語句,而update語句回滾的核心在於計算出每個AI、BI的長度。下面介紹下長度以及部分字段的計算方法。

鏡像長度計算

鏡像是由一個個字段組成的,根據字段類型的不同,其計算長度的方法也不一樣。

  • 只與字段類型相關。比如int佔用4個字節,bingint佔用8個字節。其中類型信息可以從table map event中獲取。

  • 與字段類型及其參數相關。比如decimal(18,9),佔用9個字節,參數信息在table map event中。

  • 與字段類型、參數以及實際存儲的值相關。比如varchar(10),有1個字節表示長度,之後的字節才表示真正的數據。比如varchar(280),有2個字節表示長度。實際的長度和數據在一起。

解析binlog中的若干個關鍵點

① length encoded integer

binlog中一個或者多個字節組合,分別表示了不同的含義。比如,timestamp是由固定的4個字節組成,event類型由一個字節表示;數據庫名和表名最長為64個字符,即使每個字符佔用3個字節,那麼佔用的字節數為192<255。因此最多使用一個字節,就可以完成實際長度表示。

然而列的實際數量,可能需要超過1個字節、2個字節、3個字節甚至8個字節去表示。如果我們使用最大的8個字節去表示,那麼在絕大多數情況下都是浪費存儲空間的。針對這種情況,length encoded integer應運而生。

MyFlash——美團點評的開源MySQL閃回工具

比如在獲取一個varchar類型的長度時,首先讀取第一個字節,如果值小於251,那麼varchar的長度就是第一個字節表示的長度。如果第一個字節的值為0xFC,那麼varchar的長度是由該字節之後的後兩個字節組成,以此類推。

② decimal類型

decimal是由整數部分和小數部分組成。無論是整數還是小數,每9個數字,需要4個字節。如果不是9的倍數,剩餘的小數位,需要的字節數如下,為方便描述,將該關係定義為函數Fnum。

MyFlash——美團點評的開源MySQL閃回工具

舉例,對於 decimal(18,10):

  1. 整數部分可展示的為8,用int,即4個字節。

  2. 小數部分,需要的字節數為 (10 /9)*4+Fnum(10%9)=5。

  3. 那麼總共加起來需要4+5=9個字節。

閃回工具架構

在上面的章節中,介紹了單個binlog event的反轉方法。在實踐中,我們往往需要把某個binlog,按照指定的條件,過濾出需要的binlog,並進行反轉。那麼MyFlash是如何完成這些目標的呢?

解析binlog

首先把binlog文件,解析成多個event,放入到相關隊列中。在實現上,為了儘可能加快解析速度,可以讓用戶指定解析的開始與結束位置。把binlog文件解析成binlog event後,再判斷下是否符合指定的時間條件,若不符合,則丟棄該event。

MyFlash——美團點評的開源MySQL閃回工具

注意:用戶可以不指定位置和時間,則解析整個文件。如果只指定時間,那麼也需要從文件開始處解析,取出時間信息,再進行判斷。因此,當需要回滾的binlog只佔整個binlog的一小部分時,推薦使用指定位置。

MyFlash——美團點評的開源MySQL閃回工具

重組event

把binlog event組成最小執行單元。在常見的binlog event中table_map event包含了所要了表名、庫名等元數據信息,而row_event(包含write_event、delete_event、update_event)包含了真正的數據。因此在設計中使用了一個最小執行單元概念。所謂的最小執行單元,即least execution event unit,通常包含一個table_map event和若干個row_event。

MyFlash——美團點評的開源MySQL閃回工具

比如在binlog格式概覽一節中,介紹了table_map_event和update_row_event。如果只有update_row_event,那麼我們無法知道這個event對應的行記錄變更對應的表。因此一個完整的最小執行單元最少包含一個table_map_event和write_row_event、update_row_even、delete_row_event中的一個。

為什麼我們需要使用最小執行單元?因為我們在閃回操作時,不能簡單的把每個event反轉之後,然後再將所有event的順序反轉過來。如果這樣的話,就會出現table_map event在row event之後,這顯然是違反binlog執行邏輯的。

有了最小執行單元之後,只需兩步,即可完成反轉。

a. 反轉最小執行單元中的row event。

b. 逆序最小執行單元隊列,即可。

當然在反轉前,也可以增加過濾操作。比如過濾庫名、表名和SQL類型等。

MyFlash——美團點評的開源MySQL閃回工具

生成binlog文件

有了逆序的最小執行單元隊列後,只需把每個最小執行單元依次輸入到文件即可。不過不要忘了修改每個binlog event裡的next_position,用來表示下一個binlog的位置。

性能對比

測試場景

使用testFlashback2,插入100萬條數據:

CREATE TABLE `testFlashback2` ( `id` int(11) NOT NULL AUTO_INCREMENT, `nameShort` varchar(20) DEFAULT NULL, `nameLong` varchar(260) DEFAULT NULL, `amount` decimal(19,9) DEFAULT NULL, `amountFloat` float DEFAULT NULL, `amountDouble` double DEFAULT NULL, `createDatetime6` datetime(6) DEFAULT NULL, `createDatetime` datetime DEFAULT NULL, `createTimestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `nameText` text, `nameBlob` blob, `nameMedium` mediumtext, PRIMARY KEY (`id`)) ENGINE=InnoDBmysql> select count(*) from testFlashback2;+----------+| count(*) |+----------+| 1048576 |+----------+1 row in set (0.16 sec)delete from testFlashback2;

測試結果

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

MyFlash——美團點評的開源MySQL閃回工具

每個event都是由event header 和event data組成。下面簡單介紹下幾種常見的binlog event。

① formart description event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

170905 01:59:33 server id 10 end_log_pos 123 CRC32 0xed1ec563Start: binlog v 4, server v 5.7.18-log created 170905 01:59:33

② table map event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 339 CRC32 0x3de40c0d  Table_map: `test`.`test4` mapped to number 238

③ update row event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 385 CRC32 0x179ef6dd  Update_rows: table id 238 flags: STMT_END_F UPDATE `test`.`test4` WHERE @1=3 SET @1=13;

binlog event回滾

根據上面的binlog介紹,可以看到每個binlog event中event header有個type_code,其中insert為30,update為31,delete為32。對於insert和delete兩個相反的操作,只需把type_code互換,則在binlog event級別完成回滾。

MyFlash——美團點評的開源MySQL閃回工具

而對於update操作,其格式如下。

MyFlash——美團點評的開源MySQL閃回工具

其中,BI是指before image,AI是指after image。

我們只需依次遍歷修改前的數據和修改後的數據,並一一互換即可。因此整個回滾操作的難點在於回滾update語句,而update語句回滾的核心在於計算出每個AI、BI的長度。下面介紹下長度以及部分字段的計算方法。

鏡像長度計算

鏡像是由一個個字段組成的,根據字段類型的不同,其計算長度的方法也不一樣。

  • 只與字段類型相關。比如int佔用4個字節,bingint佔用8個字節。其中類型信息可以從table map event中獲取。

  • 與字段類型及其參數相關。比如decimal(18,9),佔用9個字節,參數信息在table map event中。

  • 與字段類型、參數以及實際存儲的值相關。比如varchar(10),有1個字節表示長度,之後的字節才表示真正的數據。比如varchar(280),有2個字節表示長度。實際的長度和數據在一起。

解析binlog中的若干個關鍵點

① length encoded integer

binlog中一個或者多個字節組合,分別表示了不同的含義。比如,timestamp是由固定的4個字節組成,event類型由一個字節表示;數據庫名和表名最長為64個字符,即使每個字符佔用3個字節,那麼佔用的字節數為192<255。因此最多使用一個字節,就可以完成實際長度表示。

然而列的實際數量,可能需要超過1個字節、2個字節、3個字節甚至8個字節去表示。如果我們使用最大的8個字節去表示,那麼在絕大多數情況下都是浪費存儲空間的。針對這種情況,length encoded integer應運而生。

MyFlash——美團點評的開源MySQL閃回工具

比如在獲取一個varchar類型的長度時,首先讀取第一個字節,如果值小於251,那麼varchar的長度就是第一個字節表示的長度。如果第一個字節的值為0xFC,那麼varchar的長度是由該字節之後的後兩個字節組成,以此類推。

② decimal類型

decimal是由整數部分和小數部分組成。無論是整數還是小數,每9個數字,需要4個字節。如果不是9的倍數,剩餘的小數位,需要的字節數如下,為方便描述,將該關係定義為函數Fnum。

MyFlash——美團點評的開源MySQL閃回工具

舉例,對於 decimal(18,10):

  1. 整數部分可展示的為8,用int,即4個字節。

  2. 小數部分,需要的字節數為 (10 /9)*4+Fnum(10%9)=5。

  3. 那麼總共加起來需要4+5=9個字節。

閃回工具架構

在上面的章節中,介紹了單個binlog event的反轉方法。在實踐中,我們往往需要把某個binlog,按照指定的條件,過濾出需要的binlog,並進行反轉。那麼MyFlash是如何完成這些目標的呢?

解析binlog

首先把binlog文件,解析成多個event,放入到相關隊列中。在實現上,為了儘可能加快解析速度,可以讓用戶指定解析的開始與結束位置。把binlog文件解析成binlog event後,再判斷下是否符合指定的時間條件,若不符合,則丟棄該event。

MyFlash——美團點評的開源MySQL閃回工具

注意:用戶可以不指定位置和時間,則解析整個文件。如果只指定時間,那麼也需要從文件開始處解析,取出時間信息,再進行判斷。因此,當需要回滾的binlog只佔整個binlog的一小部分時,推薦使用指定位置。

MyFlash——美團點評的開源MySQL閃回工具

重組event

把binlog event組成最小執行單元。在常見的binlog event中table_map event包含了所要了表名、庫名等元數據信息,而row_event(包含write_event、delete_event、update_event)包含了真正的數據。因此在設計中使用了一個最小執行單元概念。所謂的最小執行單元,即least execution event unit,通常包含一個table_map event和若干個row_event。

MyFlash——美團點評的開源MySQL閃回工具

比如在binlog格式概覽一節中,介紹了table_map_event和update_row_event。如果只有update_row_event,那麼我們無法知道這個event對應的行記錄變更對應的表。因此一個完整的最小執行單元最少包含一個table_map_event和write_row_event、update_row_even、delete_row_event中的一個。

為什麼我們需要使用最小執行單元?因為我們在閃回操作時,不能簡單的把每個event反轉之後,然後再將所有event的順序反轉過來。如果這樣的話,就會出現table_map event在row event之後,這顯然是違反binlog執行邏輯的。

有了最小執行單元之後,只需兩步,即可完成反轉。

a. 反轉最小執行單元中的row event。

b. 逆序最小執行單元隊列,即可。

當然在反轉前,也可以增加過濾操作。比如過濾庫名、表名和SQL類型等。

MyFlash——美團點評的開源MySQL閃回工具

生成binlog文件

有了逆序的最小執行單元隊列後,只需把每個最小執行單元依次輸入到文件即可。不過不要忘了修改每個binlog event裡的next_position,用來表示下一個binlog的位置。

性能對比

測試場景

使用testFlashback2,插入100萬條數據:

CREATE TABLE `testFlashback2` ( `id` int(11) NOT NULL AUTO_INCREMENT, `nameShort` varchar(20) DEFAULT NULL, `nameLong` varchar(260) DEFAULT NULL, `amount` decimal(19,9) DEFAULT NULL, `amountFloat` float DEFAULT NULL, `amountDouble` double DEFAULT NULL, `createDatetime6` datetime(6) DEFAULT NULL, `createDatetime` datetime DEFAULT NULL, `createTimestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `nameText` text, `nameBlob` blob, `nameMedium` mediumtext, PRIMARY KEY (`id`)) ENGINE=InnoDBmysql> select count(*) from testFlashback2;+----------+| count(*) |+----------+| 1048576 |+----------+1 row in set (0.16 sec)delete from testFlashback2;

測試結果

MyFlash——美團點評的開源MySQL閃回工具

由於運維、DBA的誤操作或是業務bug,我們在操作中時不時會出現誤刪除數據情況。早期要想恢復數據,只能讓業務人員根據線上操作日誌,構造誤刪除的數據,或者DBA使用binlog和備份的方式恢復數據,不管那種,都非常費時費力,而且容易出錯。直到彭立勳首次在MySQL社區為mysqlbinlog擴展了閃回功能。

在美團點評,我們也遇到過研發人員誤刪主站的配置信息,從而導致主站長達2個小時不可用的情況。DBA同學當時使用了技術團隊自研的binlog2sql完成了數據恢復,並多次挽救了線上誤刪數據導致的嚴重故障。不過,binlog2sql在恢復速度上不盡如人意,因此我們開發了一個新的工具——MyFlash,它很好地解決了上述痛點,能夠方便並且高效地進行數據恢復。

現在該工具正式開源,開源地址為:https://github.com/Meituan-Dianping/MyFlash 。

閃回工具現狀

先來看下目前市面上已有的恢復工具,我們從實現角度把它們劃分成如下幾類。

① mysqlbinlog工具配合sed、awk。該方式先將binlog解析成類SQL的文本,然後使用sed、awk把類SQL文本轉換成真正的SQL。

  • 優點:當SQL中字段類型比較簡單時,可以快速生成需要的SQL,且編程門檻也比較低。

  • 缺點:當SQL中字段類型比較複雜時,尤其是字段中的文本包含HTML代碼,用awk、sed等工具時,就需要考慮極其複雜的轉義等情況,出錯概率很大。

② 給數據庫源碼打patch。該方式擴展了mysqlbinlog的功能,增加Flashback選項。

  • 優點:複用了MySQL Server層中binlog解析等代碼,一旦穩定之後,無須關心複雜的字段類型,且效率較高。

  • 缺點:在修改前,需要對MySQL的複製代碼結構和細節需要較深的瞭解。版本比較敏感,在MySQL 5.6上做的patch,基本不能用於MySQL 5.7的回滾操作。升級困難,因為patch的代碼是分佈在MySQL的各個文件和函數中,一旦MySQL代碼改變,特別是複製層的重構,升級的難度不亞於完全重新寫一個。

③ 使用業界提供的解析binlog的庫,然後進行SQL構造,其優秀代表是binlog2sql。

  • 優點:使用業界成熟的庫,因此穩定性較好,且上手難度較低。

  • 缺點:效率往往較低,且實現上受制於binlog庫提供的功能。

上述幾種實現方式,主要是提供的過濾選項較少,比如不能提供基於SQL類型的過濾,需要回滾一個delete語句,導致在回滾時,需要結合awk、sed等工具進行篩選。

總結了上述幾種工具的優缺點,我認為理想的閃回工具需要有以下特性。

a. 無需把binlog解析成文本,再進行轉換。

b. 提供原生的基於庫、表、SQL類型、位置、時間等多種過濾方式。

c. 支持MySQL多個版本。

d. 對於數據庫的代碼重構不敏感,利於升級。

e. 自主掌控binlog解析,提供儘可能靈活的方式。

在這些特性中,binlog的解析是一切工作的基礎。接下來我會介紹binlog的基本結構。

binlog格式初探

binlog格式概覽

一個完整的binlog文件是由一個format description event開頭,一個rotate event結尾,中間由多個其他event組合而成。

MyFlash——美團點評的開源MySQL閃回工具

binlog文件實例:

MyFlash——美團點評的開源MySQL閃回工具

每個event都是由event header 和event data組成。下面簡單介紹下幾種常見的binlog event。

① formart description event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

170905 01:59:33 server id 10 end_log_pos 123 CRC32 0xed1ec563Start: binlog v 4, server v 5.7.18-log created 170905 01:59:33

② table map event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 339 CRC32 0x3de40c0d  Table_map: `test`.`test4` mapped to number 238

③ update row event

MyFlash——美團點評的開源MySQL閃回工具

表達的含義是:

 170905 01:59:33 server id 10 end_log_pos 385 CRC32 0x179ef6dd  Update_rows: table id 238 flags: STMT_END_F UPDATE `test`.`test4` WHERE @1=3 SET @1=13;

binlog event回滾

根據上面的binlog介紹,可以看到每個binlog event中event header有個type_code,其中insert為30,update為31,delete為32。對於insert和delete兩個相反的操作,只需把type_code互換,則在binlog event級別完成回滾。

MyFlash——美團點評的開源MySQL閃回工具

而對於update操作,其格式如下。

MyFlash——美團點評的開源MySQL閃回工具

其中,BI是指before image,AI是指after image。

我們只需依次遍歷修改前的數據和修改後的數據,並一一互換即可。因此整個回滾操作的難點在於回滾update語句,而update語句回滾的核心在於計算出每個AI、BI的長度。下面介紹下長度以及部分字段的計算方法。

鏡像長度計算

鏡像是由一個個字段組成的,根據字段類型的不同,其計算長度的方法也不一樣。

  • 只與字段類型相關。比如int佔用4個字節,bingint佔用8個字節。其中類型信息可以從table map event中獲取。

  • 與字段類型及其參數相關。比如decimal(18,9),佔用9個字節,參數信息在table map event中。

  • 與字段類型、參數以及實際存儲的值相關。比如varchar(10),有1個字節表示長度,之後的字節才表示真正的數據。比如varchar(280),有2個字節表示長度。實際的長度和數據在一起。

解析binlog中的若干個關鍵點

① length encoded integer

binlog中一個或者多個字節組合,分別表示了不同的含義。比如,timestamp是由固定的4個字節組成,event類型由一個字節表示;數據庫名和表名最長為64個字符,即使每個字符佔用3個字節,那麼佔用的字節數為192<255。因此最多使用一個字節,就可以完成實際長度表示。

然而列的實際數量,可能需要超過1個字節、2個字節、3個字節甚至8個字節去表示。如果我們使用最大的8個字節去表示,那麼在絕大多數情況下都是浪費存儲空間的。針對這種情況,length encoded integer應運而生。

MyFlash——美團點評的開源MySQL閃回工具

比如在獲取一個varchar類型的長度時,首先讀取第一個字節,如果值小於251,那麼varchar的長度就是第一個字節表示的長度。如果第一個字節的值為0xFC,那麼varchar的長度是由該字節之後的後兩個字節組成,以此類推。

② decimal類型

decimal是由整數部分和小數部分組成。無論是整數還是小數,每9個數字,需要4個字節。如果不是9的倍數,剩餘的小數位,需要的字節數如下,為方便描述,將該關係定義為函數Fnum。

MyFlash——美團點評的開源MySQL閃回工具

舉例,對於 decimal(18,10):

  1. 整數部分可展示的為8,用int,即4個字節。

  2. 小數部分,需要的字節數為 (10 /9)*4+Fnum(10%9)=5。

  3. 那麼總共加起來需要4+5=9個字節。

閃回工具架構

在上面的章節中,介紹了單個binlog event的反轉方法。在實踐中,我們往往需要把某個binlog,按照指定的條件,過濾出需要的binlog,並進行反轉。那麼MyFlash是如何完成這些目標的呢?

解析binlog

首先把binlog文件,解析成多個event,放入到相關隊列中。在實現上,為了儘可能加快解析速度,可以讓用戶指定解析的開始與結束位置。把binlog文件解析成binlog event後,再判斷下是否符合指定的時間條件,若不符合,則丟棄該event。

MyFlash——美團點評的開源MySQL閃回工具

注意:用戶可以不指定位置和時間,則解析整個文件。如果只指定時間,那麼也需要從文件開始處解析,取出時間信息,再進行判斷。因此,當需要回滾的binlog只佔整個binlog的一小部分時,推薦使用指定位置。

MyFlash——美團點評的開源MySQL閃回工具

重組event

把binlog event組成最小執行單元。在常見的binlog event中table_map event包含了所要了表名、庫名等元數據信息,而row_event(包含write_event、delete_event、update_event)包含了真正的數據。因此在設計中使用了一個最小執行單元概念。所謂的最小執行單元,即least execution event unit,通常包含一個table_map event和若干個row_event。

MyFlash——美團點評的開源MySQL閃回工具

比如在binlog格式概覽一節中,介紹了table_map_event和update_row_event。如果只有update_row_event,那麼我們無法知道這個event對應的行記錄變更對應的表。因此一個完整的最小執行單元最少包含一個table_map_event和write_row_event、update_row_even、delete_row_event中的一個。

為什麼我們需要使用最小執行單元?因為我們在閃回操作時,不能簡單的把每個event反轉之後,然後再將所有event的順序反轉過來。如果這樣的話,就會出現table_map event在row event之後,這顯然是違反binlog執行邏輯的。

有了最小執行單元之後,只需兩步,即可完成反轉。

a. 反轉最小執行單元中的row event。

b. 逆序最小執行單元隊列,即可。

當然在反轉前,也可以增加過濾操作。比如過濾庫名、表名和SQL類型等。

MyFlash——美團點評的開源MySQL閃回工具

生成binlog文件

有了逆序的最小執行單元隊列後,只需把每個最小執行單元依次輸入到文件即可。不過不要忘了修改每個binlog event裡的next_position,用來表示下一個binlog的位置。

性能對比

測試場景

使用testFlashback2,插入100萬條數據:

CREATE TABLE `testFlashback2` ( `id` int(11) NOT NULL AUTO_INCREMENT, `nameShort` varchar(20) DEFAULT NULL, `nameLong` varchar(260) DEFAULT NULL, `amount` decimal(19,9) DEFAULT NULL, `amountFloat` float DEFAULT NULL, `amountDouble` double DEFAULT NULL, `createDatetime6` datetime(6) DEFAULT NULL, `createDatetime` datetime DEFAULT NULL, `createTimestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `nameText` text, `nameBlob` blob, `nameMedium` mediumtext, PRIMARY KEY (`id`)) ENGINE=InnoDBmysql> select count(*) from testFlashback2;+----------+| count(*) |+----------+| 1048576 |+----------+1 row in set (0.16 sec)delete from testFlashback2;

測試結果

MyFlash——美團點評的開源MySQL閃回工具

MyFlash——美團點評的開源MySQL閃回工具

從上述圖表中可以看出,MyFlash的速度最快。

參考文檔

  1. MySQL官方文檔1,2,3.

  2. binlog2sql.

  3. mysqlbinlog Flashback for 5.6.

  4. MySQL閃回原理與實戰.

相關推薦

推薦中...