MySQL中binlog cache使用流程解惑

gaopengtttt發表於2018-07-04

水平有限整理自己的學習筆記,如果有誤請諒解。

最近老是看到有朋友報錯如下:
ERROR 1197 (HY000): Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again
雖然錯誤提示非常明確,但是我還是對binlog cache的使用方式進行了學習整理下來,這部分也是我一直疑惑的地方,也希望通過本文接觸讀者的疑惑。

本文約定:

  • binlog cache:實際上就是引數binlog_cache_size指定的大小,它指定的是一段記憶體空間用於儲存生成的binlog event,是事物級別的引數。
  • binlog cache 臨時檔案:實際上就是引數max_binlog_cache_size指定的大小,它指定是一個臨時磁碟檔案儲存由於binlog cache不足溢位的binlog event,其名字由"ML"打頭,是事物級別的引數。
  • binlog file:代表就是我們平時說的binglog 檔案,由max_binlog_size指定大小。
  • binlog event:代表是各種各樣的binlog中的記錄比如MAP_EVENT/QUERY EVENT/XID EVENT/WRITE EVENT等。

本文原始碼版本:

  • percona 5.7.14

一、通常事物binlog event的寫入流程

這裡首先給出寫入過程,讓大家有一個大概的理解。

注意這個流程都是對於一個事物來講的。一旦事物提交,binlog cache和binlog 臨時檔案都會釋放掉,因為binlog已經固化到了binlog file。同時如果事物中包含多個DML語句,那麼他們共享的一套的binlog cache和binlog 臨時檔案。

  1. 事物開啟。
  2. 執行dml語句,在dml語句第一次執行的時候會分配記憶體空間binlog cache
  3. 執行dml語句期間生成的event不斷寫入到binlog cache。
  4. 如果binlog cache的空間已經滿了,則將binlog cache的資料寫入到binlog臨時檔案,同時清空binlog cache。如果binlog臨時檔案的大小大於了max_binlog_cache_size的設定則拋錯ERROR 1197 (HY000)。
  5. 事物提交,整個binlog cache和binlog臨時檔案資料全部寫入到binlog file中進行固化,釋放binlog cache和binlog臨時檔案。但是注意此時binlog cache的記憶體空間留用供下次事物使用,但是binlog臨時檔案被截斷為0,保留檔案描述符。其實也就是IO_CACHE(參考後文)保留,並且保留IO_CACHE中的分配的記憶體空間,和物理檔案描述符。
  6. 斷開連線,這個過程會釋放IO_CACHE同時釋放其持有的binlog cache記憶體空間以及持有的binlog 臨時檔案。

本文研究就是步驟3和步驟4的寫入過程,和binlog cache以及binlog 臨時檔案的實現方式。同時本文不描述binlog_stmt_cache_size和max_binlog_stmt_cache_size的作用,因為他們和binlog_cache_size、max_binlog_cache_size引數的函式一致,只是儲存是非事物語句的binlog event,但是在討論資料結構的時候還是給出部分解釋。

二、相關資料結構簡介

  • binlog_cache_mngr類:
    這個類中包含了兩個cache實際上就是binlog cache和binlog stmt cache,如下:
    1. binlog_stmt_cache_data stmt_cache;
    2. binlog_trx_cache_data trx_cache;
      其中包含一些方法用於訪問這兩個cache。同時將整個binlog event寫入到binlog file的方法也在其中叫做flush,棧幀如下:
#0 binlog_cache_mngr::flush (this=0x7fff58ca17c0, thd=0x7fff58012930, bytes_written=0x7ffff0358918, wrote_xid=0x7ffff0358917)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:739 #1 0x0000000001857152 in MYSQL_BIN_LOG::flush_thread_caches (this=0x2e02c80, thd=0x7fff58012930) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:8484 #2 0x0000000001857383 in MYSQL_BIN_LOG::process_flush_stage_queue (this=0x2e02c80, total_bytes_var=0x7ffff0358a88, rotate_var=0x7ffff0358a87, 
    out_queue_var=0x7ffff0358a78) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:8546 #3 0x000000000185899f in MYSQL_BIN_LOG::ordered_commit (this=0x2e02c80, thd=0x7fff58012930, all=false, skip_commit=false)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:9189 #4 0x000000000185700c in MYSQL_BIN_LOG::commit (this=0x2e02c80, thd=0x7fff58012930, all=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:8440 

可以說他是一個訪問binlog cache和binlog stmt cache的統一的對外介面。

  • binlog_trx_cache_data類和binlog_stmt_cache_data類:

他們都繼承來自統一的父類binlog_cache_data。因為binlog_trx_cache_data要實現更多的功能,因為要支援事物,支援事物的回滾等功能,所以必須增加額外的功能呢但是。binlog_stmt_cache_data則不需要。

  • binlog_cache_data類:

實現了主要成員包含:

  1. IO_CACHE cache_log:Cache to store data before copying it to the binary log.實際上所謂的binlog cache(binlog stmt cache)/max binlog cache(max stmt binlog cache)都是他實現的。
  2. Rows_log_event *m_pending:Pending binrows event. This event is the event where the rows are currently written.
  3. my_off_t saved_max_binlog_cache_size:引數max_binlog_cache_size/max_binlog_stmt_cache_size的大小。
  4. ulong *ptr_binlog_cache_use:狀態binlog_cache_use/binlog_stmt_cache_use的值的指標。
  5. ulong *ptr_binlog_cache_disk_use:狀態binlog_cache_disk_use/binlog_stmt_cache_disk_use的值的指標。
  • IO_CACHE類:

實際上binlog event的寫入binlog 或者 binlog臨時檔案都是由 IO_CACHE子系統實現的,本子系統實現了類似寫快取如果快取不夠寫入物理檔案的功能,從而降低了物理寫入的次數,提升了效能。它封裝了包含讀快取,寫快取以及物理檔案等資訊。如下:

  1. 讀快取 uchar *buffer;
  2. 寫快取 uchar *write_buffer;
  3. 物理檔案描述符 File file;

其使用方式也分多種模式如:

  1. READ_CACHE模式
  2. WRITE_CACHE模式
  3. SEQ_READ_APPEND模式

當然IO_CACHE還用到其他地方,比如我們熟悉的filesort,進行記憶體和磁碟排序也是通過這個子系統作為儲存方式完成的。棧幀參考結束附錄,對於這個子系統更加詳細的參考資訊可以自行百度我發現有朋友寫得很清楚,本文主要說明是binlog cache的使用方式而不是這個子系統。但是在涉及到原始碼部分的時候以binlog cache和binlog臨時檔案的寫入為列子。

最後我們畫一張這幾個類的關係圖,同時給出binlog cache(binlog stmt cache)和binlog臨時檔案(binlog stmt臨時檔案)的表示,如下:

MySQL中binlog cache使用流程解惑
QQ圖片20180703183344.png

這張圖解釋了他們的關係。

三、binlog_cache_size作用及其初始化

本節使用的binlog_cache_size大小為32678及預設值。

binlog_cache_size引數在官方文件的描述大概為如果開啟了binlog功能,則在事物期間用於儲存binlog event的快取。如果經常使用大事物應該加大這個快取,避免過多的磁碟使用,從Binlog_cache_use和Binlog_cache_disk_use可以看出是否使用了binlog cache或binlog 臨時檔案用於儲存binlog event。
當然如我開頭所說這部分是完全記憶體的。
實際上當我們的事物需要記錄事物的binlog event的時候我們就會使用到binlog cache,其初始化棧幀如下:

#0  init_io_cache_ext (info=0x7fff58ca17c8, file=-1, cachesize=32768, type=WRITE_CACHE, seek_offset=0, use_async_io=0 '\000', cache_myflags=20, file_key=10) at /root/mysql5.7.14/percona-server-5.7.14-7/mysys/mf_iocache.c:154 #1  0x00000000018c8b48 in init_io_cache (info=0x7fff58ca17c8, file=-1, cachesize=32768, type=WRITE_CACHE, seek_offset=0, use_async_io=0 '\000', cache_myflags=20) at /root/mysql5.7.14/percona-server-5.7.14-7/mysys/mf_iocache.c:299 #2  0x00000000018c6b96 in open_cached_file (cache=0x7fff58ca17c8, dir=0x2fa1d70 "/root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/tmp/mysqld.1",  prefix=0x2277d4e "ML", cache_size=32768, cache_myflags=16) at /root/mysql5.7.14/percona-server-5.7.14-7/mysys/mf_cache.c:60 #3  0x00000000018599b2 in THD::binlog_setup_trx_data (this=0x7fff58012930) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:9641 #4  0x0000000001859cb3 in binlog_start_trans_and_stmt (thd=0x7fff58012930, start_event=0x7ffff0359350) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:9742 #5  0x000000000185a0a6 in THD::binlog_write_table_map (this=0x7fff58012930, table=0x7fff58d98260, is_transactional=false, binlog_rows_query=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:9835 #6  0x0000000000f7299f in write_locked_table_maps (thd=0x7fff58012930) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/handler.cc:8019 #7  0x0000000000f72bf6 in binlog_log_row (table=0x7fff58d98260, before_record=0x7fff58d99120 "\375\001", after_record=0x0,  log_func=0xf77f7d <delete_rows_log_event::binlog_row_logging_function(thd*, table*,="" bool, uchar const*, uchar const*)>)
    at /root/mysql5.7.14/percona-server-5.7.14-7/sql/handler.cc:8089 

我們可以在THD::binlog_setup_trx_data找到binlog_cache_size的作如下:

open_cached_file(&cache_mngr->trx_cache.cache_log, mysql_tmpdir,
                       LOG_PREFIX, binlog_cache_size, MYF(MY_WME))) 

大概解釋一下部分引數的含義。

  • &cache_mngr->trx_cache.cache_log 就是一個IO_CACHE例項。
  • mysql_tmpdir 為引數tmpdir的定義目錄。
  • LOG_PREFIX 為如果使用臨時檔案臨時檔案的字首,如果是binlog的臨時磁碟檔案則為"ML",如果是filesort的臨時排序檔案則為"MY"。
  • cache_size 當然就是你引數binlog_cache_size設定的大小。

最終引數binlog_cache_size的值會通過init_io_cache函式傳入到init_io_cache_ext中。我們關注一下以下幾個傳入到init_io_cache_ext的引數。

  • file=-1:初始換快取的情況下,不會非配實際的臨時檔案。索引用-1表示檔案描述符
  • cachesize=32768:binlog_cache_size設定的大小。
  • type=WRITE_CACHE:IO_CACHE的使用模式。

下面是init_io_cache_ext函式關於binlog cache分配的重點程式碼部分:

 info->file= file;(-1)
      info->pos_in_file= seek_offset;(0)
      info->pre_close = info->pre_read = info->post_read = 0;
        info->arg = 0;
        info->alloced_buffer = 0;
        info->buffer=0;
        info->seek_not_done= 0;
            
      buffer_block= cachesize; //他們和binlog_cache_size引數指定相等(有對其操作) if ((info->buffer= (uchar*) my_malloc(key_memory_IO_CACHE,
                                            buffer_block, flags)) != 0)//為binlog cache分配實際的記憶體其大小就是binlog_cache_size指定的大小(有對其操作) {
        info->write_buffer=info->buffer;//write_buffer和buffer指向了同一片記憶體區域,及我們的binlog cache快取區域 info->alloced_buffer=1;
      }
      info->read_length=info->buffer_length=cachesize; //此處將快取的長度記錄為binlog_cache_size指定的大小(有對其操作) info->request_pos= info->read_pos= info->write_pos = info->buffer;//初始化各種位置為info->buffer指標指向的位置 if (type == WRITE_CACHE)
      info->write_end= info->buffer+info->buffer_length- (seek_offset & (IO_SIZE-1));//將快取的邊界設定為(info->buffer指標指向位置+binlog_cache_size引數指定的大小) 

此後IO_CACHE物件已經分配了一塊binlog_cache_size引數指定相等大小的記憶體,則使我們說的binlog cache已經初始化分配完成。

四、binlog臨時檔案的使用和分配方式

及當我們事物需要儲存的binlog event已經不能在binlog cache中存下的時候,我們需要開啟我們binlong臨時檔案來儲存。其檔案存放到tmpdir的定義的目錄下,檔名為”ML”開頭。但是這個檔案不能用ls看到,因為使用了LINUX臨時檔案建立的方法,以避免其他程式使用這個檔案而破壞這個檔案的內容。也就是說,這個檔案是mysqld程式內部專用的,在LINUX中MySQL使用mkstemp系統呼叫完成這個功能。對於這個檔案可以使用lsof|grep delete看到最後我會給出一個例子。

分配棧幀如下:

#0  create_temp_file (to=0x7ffff0359040 "/root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/tmp/mysqld.1/MLIdFGCH",  dir=0x7fff580167c0 "/root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/tmp/mysqld.1", prefix=0x7fff58016830 "ML", mode=514, MyFlags=16)
    at /root/mysql5.7.14/percona-server-5.7.14-7/mysys/mf_tempfile.c:141 #1  0x00000000018c693d in inline_mysql_file_create_temp (key=10, src_file=0x2296d78 "/root/mysql5.7.14/percona-server-5.7.14-7/mysys/mf_cache.c", src_line=80,  to=0x7ffff0359040 "/root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/tmp/mysqld.1/MLIdFGCH", 
    dir=0x7fff580167c0 "/root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/tmp/mysqld.1", pfx=0x7fff58016830 "ML", mode=514, myFlags=16)
    at /root/mysql5.7.14/percona-server-5.7.14-7/include/mysql/psi/mysql_file.h:1048 #2  0x00000000018c6c87 in real_open_cached_file (cache=0x7fff58ca17c8) at /root/mysql5.7.14/percona-server-5.7.14-7/mysys/mf_cache.c:77 #3  0x00000000018cb4a9 in my_b_flush_io_cache (info=0x7fff58ca17c8, need_append_buffer_lock=0) at /root/mysql5.7.14/percona-server-5.7.14-7/mysys/mf_iocache.c:1528 #4  0x00000000018cad03 in _my_b_write (info=0x7fff58ca17c8, Buffer=0x7fff58de751a "", Count=186) at /root/mysql5.7.14/percona-server-5.7.14-7/mysys/mf_iocache.c:1330 #5  0x00000000018cb156 in my_b_safe_write (info=0x7fff58ca17c8, Buffer=0x7fff58de55e0 "\376\001", Count=8180) at /root/mysql5.7.14/percona-server-5.7.14-7/mysys/mf_iocache.c:1437 #6  0x000000000180e7b2 in Log_event::wrapper_my_b_safe_write (this=0x7fff58972bb0, file=0x7fff58ca17c8, buf=0x7fff58de55e0 "\376\001", size=8180) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/log_event.cc:977 #7  0x000000000182b392 in Rows_log_event::write_data_body (this=0x7fff58972bb0, file=0x7fff58ca17c8) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/log_event.cc:11356 #8  0x0000000001835e63 in Log_event::write (this=0x7fff58972bb0, file=0x7fff58ca17c8) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/log_event.h:825 #9  0x0000000001845899 in binlog_cache_data::write_event (this=0x7fff58ca17c0, thd=0x7fff58012930, ev=0x7fff58972bb0) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:1120 #10 0x0000000001853625 in MYSQL_BIN_LOG::flush_and_set_pending_rows_event (this=0x2e02c80, thd=0x7fff58012930, event=0x7fff58954fd0, is_transactional=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:7075 

當我們不斷的寫入binlog event的情況下,我們最終會將binlog cache寫滿(對於小事物肯定不會寫滿)。我們來梳理一下binlog 臨時檔案是怎麼開啟的,我們從my_b_safe_write函式開始:
注意這裡實際對於IO_CACHE來講是通用的方法我只是以binlog 臨時檔案建立的流程為例子,因為不同的模式走的邏輯不一樣

  • my_b_safe_write

這個函式在每次binlog event寫入到binlog cache的時候都會呼叫。
在WRITE_CACHE的模式下會呼叫巨集my_b_write,這是一個關鍵點巨集的定義如下:

#define my_b_write(info,Buffer,Count) \ ((info)->write_pos + (Count) <=(info)->write_end ?\
  (memcpy((info)->write_pos, (Buffer), (size_t)(Count)),\
   ((info)->write_pos+=(Count)),0) : \
   (*(info)->write_function)((info),(uchar *)(Buffer),(Count))) 

很簡單如果binlog cache快取當前寫入的位置加上本次寫入的總量大於了binlog cache的記憶體地址的邊界則我們需要進行通過*(info)->write_function這個回撥函式將binlog cache的內容寫到磁碟了,這樣才能騰出空間給新的binlog event存放。這裡這個回撥函式應該就是_my_b_write。

  • _my_b_write

這個函式只會在binlog cache不夠用的時候需要進行臨時物理檔案寫入的時候呼叫。
大概邏輯如下:

rest_length= (size_t) (info->write_end - info->write_pos); //統計出此時binlog cache剩餘的空間 memcpy(info->write_pos,Buffer,(size_t) rest_length); //寫滿這些剩餘的空間 Buffer+=rest_length;//既然已經寫了一部分那麼待寫入的資料應該減去寫入的部分 Count-=rest_length;//寫入的總量也應該的減去已經寫入的部分 info->write_pos+=rest_length;//binlog cache的寫入位置應該增加 if (my_b_flush_io_cache(info,1))//建立臨時檔案(如果沒有建立的話)並且寫入資料到臨時檔案 memcpy(info->write_pos,Buffer,(size_t) Count);//重新整理完成後。binlog cache已經騰空可以繼續使用了 info->write_pos+=Count;//簡單的增加binlog cache指標的位置 
  • my_b_flush_io_cache

這個函式主要負責了當binlog cache 寫滿後將binlog cache的資料全部寫入到binlog 臨時檔案和清空binlog cache,當然最後會增加Binlog_cache_disk_use。
大概邏輯如下:

if (info->file == -1)//如果是第一次建立臨時檔案,這裡的檔案描述為-1,前面已經分析過了 { if (real_open_cached_file(info))//開啟臨時檔案返回檔案描述符 !!!!! length=(size_t) (info->write_pos - info->write_buffer)//統計本次寫入臨時檔案資料的大小  pos_in_file=info->pos_in_file;      
info->pos_in_file+=length;//將當前檔案寫入位置加上本次寫入資料的大小及為下次檔案寫入的位置 if (mysql_file_write(info->file,info->write_buffer,length,info->myflags | MY_NABP))//將資料寫入到臨時檔案中。 info->append_read_pos=info->write_pos=info->write_buffer; //此處將info->write_pos指標指向到binlog cache緩衝開始的位置及binlog cache緩衝全部釋放 ++info->disk_writes;//Binlog_cache_disk_use增加 
  • create_temp_file
    這個函式沒什麼說的就是呼叫mkstemp來完成臨時檔案的建立,我們關注一下輸入兩個引數即可
  1. to 臨時檔案的絕對路徑
  2. dir 及臨時檔案所在的目錄
  3. prefix 臨時檔案的字首,這裡是ML

注意對於filesort的臨時檔案也是通過這個函式建立,字首為MY。

到這裡我們的binlog cache記憶體空間已經分配,並且由於事物寫入的binlog event大於了binlog cache設定的大小,binlog 臨時檔案已經分配並且進行了一次binlog cache資料寫入到binlog 臨時檔案的操作。這就是整個流程。

五、max_binlog_cache_size設定過小的報錯

報錯如下:

(root@localhost)[06:19:12] [test ;]> insert into t1 select * from t1;
ERROR 1197 (HY000): Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again 

當然報錯也很清晰告訴你原因,但是在整個流程中到底是哪裡拋錯出來的呢?實際上就是函式_my_b_write中進行的判斷。先來看看這個錯誤的錯誤碼如下:

{ "ER_TRANS_CACHE_FULL", 1197, "Multi-statement transaction required more than \'max_binlog_cache_size\' bytes of storage; increase this mysqld variable and try again" }, 

在函式_my_b_write中可以看到如下程式碼:

if (pos_in_file+info->buffer_length > info->end_of_file) //判斷binlog臨時檔案的位置加上本次需要寫盤的資料大於info->end_of_file的大小則拋錯 {
    errno=EFBIG;
    set_my_errno(EFBIG); return info->error = -1;
  } 

而拋錯的程式碼在MYSQL_BIN_LOG::check_write_error函式中如下:

 if (is_transactional)
    {
      my_message(ER_TRANS_CACHE_FULL, ER(ER_TRANS_CACHE_FULL), MYF(MY_WME));
    } 

其中info->end_of_file的大小正是來自於我們的引數max_binlog_cache_size,不再給出程式碼。

六、如何觀察到binlog 臨時檔案的存在

前文已經說過可以使用lsof|grep delete來觀察到這種檔案,據我觀察這個檔案會以64k的倍數上漲如下:

[root@test ~]# lsof|grep delete|grep ML mysqld    21414      root   77u      REG              252,3     65536    1856092 /root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/tmp/mysqld.1/MLUFzokf (deleted)
[root@test ~]# lsof|grep delete|grep ML mysqld    21414      root   77u      REG              252,3    131072    1856092 /root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/tmp/mysqld.1/MLUFzokf (deleted)
[root@test ~]# lsof|grep delete|grep ML mysqld    21414      root   77u      REG              252,3    163840    1856092 /root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/tmp/mysqld.1/MLUFzokf (deleted)
[root@test ~]# lsof|grep delete|grep ML mysqld    21414      root   77u      REG              252,3    229376    1856092 /root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/tmp/mysqld.1/MLUFzokf (deleted) 

七、總結

寫了這麼多,這裡需要總結一下引數的具體含義,以及注意點。

  • binlog_cache_size:事物級別的引數,用於指定儲存整個事物生成的binlog event的記憶體大小,對於大事物來講很可能超過這個引數的設定,則需要開啟binlog 臨時檔案用於儲存。
  • max_binlog_cache_size:事物級別的引數,用於指定當某個事物的binlog event超過了binlog_cache_size大小的設定開啟binlog 臨時檔案的可用大小,如果事物的binlog event生成量超過了max_binlog_cache_size+binlog_cache_size設定的大小則會拋錯:
ERROR 1197 (HY000): Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again 
  • 不管是binlog cache還是binlog 臨時檔案都是在事物沒有提交之前用於儲存binlog event的場所,一旦事物提交完成後,所有的binlog event都已經固化到binlog file,則它們可以釋放和重用。

  • binlog_stmt_cache_size/ max_binlog_stmt_cache_size:這一套引數和上面的兩個引數含義差不多,但是針對的是非事物型的binlog event,顯然對於innodb當道的今天大部分的event還是事物級別的,所以我沒有過多研究,但是根據debug來看DDL語句返回的是非事物級別的,如下判斷

斷點 MYSQL_BIN_LOG::write_event函式,程式碼片段如下:
    bool is_trans_cache= event_info->is_using_trans_cache();//DDL這裡返回的false binlog_cache_mngr *cache_mngr= thd_get_cache_mngr(thd);//得到cache_mngr指標地址,有了它不管是stmt快取還是trx快取都能找到如前文所述 binlog_cache_data *cache_data= cache_mngr->get_binlog_cache_data(is_trans_cache);//這裡如果是非事物級別使用stmt快取區 

八、備註資訊

最後留下一些有用的介面資訊:

  • 事物提交臨時檔案被截斷為0
    這個介面實際上就是binlog_cache_mngr::flush->binlog_cache_data::flush->binlog_cache_data::reset->my_chsize

  • 事物提交binlog cache記憶體空間留用
    這個介面可能是binlog_cache_mngr::flush->bMYSQL_BIN_LOG::write_cache->MYSQL_BIN_LOG::do_write_cache->reinit_io_cache

  • 斷開連線整個IO CACHE全部釋放掉
    這個介面就是close_cached_file如下:

File file=cache->file;
    cache->file= -1; /* Don't flush data */ (void) end_io_cache(cache);//釋放整個IO_CACHE if (file >= 0)
    {
      (void) mysql_file_close(file, MYF(0));//關閉臨時檔案 } 

作者:


MySQL中binlog cache使用流程解惑

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2157304/,如需轉載,請註明出處,否則將追究法律責任。

相關文章