MySQL 生成binlog的代碼分析

https://www.cnblogs.com/jackhub/p/3830683.html

binlog文件的內容 log event 

   MySQL的binlog文件中記錄的是對數據庫的各種修改操作,用來表示修改操作的數據結構是Log event。不同的修改操作對應的不同的log event。比較常用的幾種log event有:Query event、Row event、Xid event等。其中Query event對應的是一條SQL語句,在DDL操作和STMT格式的binlog中用的比較多。Row event是個基礎類,它的派生類有Row insert event、Row update event、Row delete event三種,分別對應ROW格式binlog的增、改、刪操作。Xid event 對應的是支持事務的commit操作,對於不支持事務的commit操作,記錄的形式是Query event。其他還有一些event,比如Format log event、Rotate event等等,可以查看MySQL的官方文檔瞭解更多相關信息。log event的種類一直在增加,比如InnoSQL中新增的checkpoint event等。要MySQL本身就留有接口以便新增一個Log event,但是新增一個Log event時需要實現幾個必要的方法函數,比如print、write、get_code_type等。binlog文件的內容就是各種Log event的集合。

產生Log event

  事務在執行DDL,或則update等操作時會記錄操作的event到線程的cache_mngr中。

  1,執行DDL操作會在db的操作函數中記錄event,這些函數有:mysql_upgrade_db,mysql_alter_db,mysql_rm_db等。其他的DDL操作會調用函數write_bin_log來記錄binlog。

  2,執行修改操作的DML語句會根據binlog格式的不同做不同的操作。若binlog格式是STMT,則記錄event的函數是binlog_query,該函數所做的事情是:

     1,根據DML操作語句構造一個Query event:

        Query_log_event qinfo(this,query_arg,query_len, ...)

     2,將event寫入緩存中

        mysql_bin_log.write(&qinfo)

     調用binlog_query的函數有:mysql_insert,mysql_delete,mysql_update等.

  3,若binlog格式是ROW,修改操作的DML語句記錄event的過程會調用binlog_log_row,每一條行的修改記錄一個Row event,所以調用binlog_log_row的都是對單個行進行修改的引擎層接口函數:ha_write_row、ha_update_row、ha_delete_row。

     函數binlog_log_row會根據行操作的具體類型分別調用三個不同的函數:binlog_write_row、binlog_update_row、binlog_delete_row。

  這三個函數的功能是:構造相應的Row event,並將行的數據寫入到Row event中。

     具體過程是:

     binlog_write_row

     1,binlog_prepare_pending_rows_event(table, server_id, cols,...);

     2,ev->add_row_data(row_data, len);

 

     binlog_update_row

     1,ev= binlog_prepare_pending_rows_event(table, server_id, cols,...);

     2,ev->add_row_data(before_row, before_size)

        ev->add_row_data(after_row, after_size)

 

     binlog_delete_row

     1,ev= binlog_prepare_pending_rows_event(table, server_id, cols,...);

     2,ev->add_row_data(row_data, len);

     新構造的Row event會在下一次記錄event的時候寫入到線程的緩存區中。

 

IO_CACHE

    寫binlog的過程都是緩存寫,使用的緩存結構是IO_CACHE。

cache_mngr,cache_data

   事務在執行過程中產生log event,這些Log event記錄在線程相關的一塊緩衝區中,每一個事務線程都有這樣一個緩存塊(前提是事務開啓了記錄binlog的功能),這塊緩存區的名稱是binlog_cache_mngr,結構如下:

class binlog_cache_mngr {

    binlog_cache_data stmt_cache; //不支持事務的存儲引擎使用的binlog緩存區

    binlog_cache_data trx_cache;  //支持事務的存儲引擎使用的binlog緩存區

    。。。

  }

   Log event保存在cache_mngr的緩存結構cache_data中,cache_data內有一個IO_CACHE緩存空間,Log event實際寫入到這個IO_CACHE中binlog_cache_data的結構如下:

class binlog_cache_data{

   IO_CACHE cache_log;

   。。。

  }

  事務執行完一個修改操作後,寫相應的Log event到線程緩存區的過程是:

  1),獲得線程的cache_mngr指針:

  cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);

  2),獲得cache_data緩存區的指針:

  cache_data= cache_mngr->get_binlog_cache_data(use_trans_cache(thd, is_transactional));

  3),將event寫入到IO_CACHE中:

   IO_CACHE *file= &cache_data->cache_log;

   event->write(file);

寫binlog

    一個事務在提交階段會將產生的log event寫入到外部binlog文件中。不同事務以串行的方式將log event寫入到外部binlog文件中,所以一個事務的所有log event在binlog文件中是連續的,中間不會插入任何其他事務的log event。MySQL整體是一個插件式的結構,binlog也是作爲一個引擎插件被上層調用,事務提交的時候MySQL上層會依次調用事務所有引擎的提交接口,binlog的提交接口第一個被調用,然後再調用其它引擎的提交接口。所以事務提交的時候是先寫binlog然後再進行底層引擎的提交過程(如InnoDB提交過程的寫redo log和刷髒頁)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章