溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

MySQL 5.7中sync_binlog參數和半同步中after_commit和after_sync的區(qū)別有哪些

發(fā)布時間:2021-11-06 09:03:09 來源:億速云 閱讀:229 作者:小新 欄目:MySQL數據庫

這篇文章給大家分享的是有關MySQL 5.7中sync_binlog參數和半同步中after_commit和after_sync的區(qū)別有哪些的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

以下討論sync_binlog參數在5.7中的作用


一、sync_binlog參數設置在源碼中的表示


這個參數大家都知道控制著binlog的刷盤時機,但是在5.7中其還有另外一個功能,我這里將解釋他的兩個功能。我摘取了源碼中說明問題的部分進行展示如下:


flush階段:
flush_error= process_flush_stage_queue(&total_bytes, &do_rotate,&wait_queue);//進行binlog的從binlog buffer或者臨時文件寫入到binlog文件(注意是寫到kernel buffer還沒做fsync),同時觸發(fā)innodb的組提交邏輯,innodb組提交的邏輯代碼是阿里的印風兄寫的,我請教過他。
update_binlog_end_pos_after_sync= (get_sync_period() == 1);//sync_binlog參數 如果為1則為真如果不為1則為假
    if (!update_binlog_end_pos_after_sync)//如果sync_binlog=1則 這里不發(fā)信號給dump 如果不是1則發(fā)信號進行dump
      update_binlog_end_pos();
其中get_sync_period()函數返回就是sync_binlog的設置,這里能夠清晰看到如果sync_binlog != 1才會 在flush階段發(fā)送信號給dump線程。


sync階段
if (flush_error == 0 && total_bytes > 0) //這里進行sync binlog,
  {
    DEBUG_SYNC(thd, "before_sync_binlog_file");
    std::pair<bool, bool> result= sync_binlog_file(false);
    sync_error= result.first;
  }


  if (update_binlog_end_pos_after_sync) //如果sync_binlog = 1 這里才發(fā)送信號給dump線程通知進行發(fā)送binlog
  {
    THD *tmp_thd= final_queue;


    while (tmp_thd->next_to_commit != NULL)
      tmp_thd= tmp_thd->next_to_commit;
    if (flush_error == 0 && sync_error == 0)
      update_binlog_end_pos(tmp_thd->get_trans_pos());
  }
如果我們翻開sync_binlog_file函數的邏輯會發(fā)現這樣一個邏輯:


if (force || (sync_period && ++sync_counter >= sync_period))
  {
    sync_counter= 0;
很顯然這里有一個計數器sync_counter,如果當sync_binlog>1的時候才,等到sync_counter大于你設置的sync_binlog的值的時候才會觸發(fā)fsync binlog(注意這里是++sync_counter 先自增再比較),這里也解釋了sync_binlog>1的時候代表的是什么值,代表是組提交的次數。


二、sync_binlog參數在5.7中作用的總結


sync_binlog=0:binlog不FSYNC刷盤,依賴于OS刷盤機制,同時dump線程會在flush階段后進行binlog傳輸
sync_binlog=1:binlog進行FSYNC刷盤,同時dump線程會在sync階段后進行binlog傳輸
sync_binlog>1:binlog將在指定次數組提交后FSYNC刷盤,同時dump線程會在flush階段后進行binlog傳輸
三、為什么這么修改


這也是一個朋友問我的問題,如果主庫異常重啟后,從庫是否有比主庫多事物的風險,實際上這個問題就是到底在什么階段后dump線程進行傳輸binlog的問題。實際上如果在flush階段過后傳輸確實可能出現這個問題,而在sync階段后傳輸這個時候binlog已經落盤了,就不會有這種風險了。如果出現這種錯誤會報錯如下,這個錯誤也是有朋友遇到過的:


ER_SLAVE_HAS_MORE_GTIDS_THAN_MASTER 
"Slave has more GTIDs than the master has, using the master's SERVER_UUID. This may indicate that the end of the binary log was truncated or that the last binary log file was lost, e.g., after a power or disk failure when sync_binlog != 1. The master may or may not have rolled back transactions that were already replicated to the slave. Suggest to replicate any transactions that master has rolled back from slave to master, and/or commit empty transactions on master to account for transactions that have been committed on master but are not included in GTID_EXECUTED." 
下面開始討論半同步中after_commit和after_sync的區(qū)別,這個問題一直也是大家討論的重點。


四、從一個問題出發(fā)討論


也是有很多朋友問我,其中一個問題如下:


半同步:after_sync模式
測試:超時時間設置為1個小時不讓主庫切換異步,同時停掉slave的I/O線程,
主庫:
session1:插入一條數據hang住
session2:插入一條數據hang住
session3:插入一條數據hang住
其中session1狀態(tài)為等待ACK,其他session狀態(tài)為query end
問為什么其他session狀態(tài)不是等待ACK而是query end。如果是after_commit模式則全部是等待ACK狀態(tài)


實際上拿到這位朋友的pstack后大概就能確認大概是什么問題如下:


等待ACK線程:
Thread 7 (Thread 0x7f44607aa700 (LWP 24897)):
#0  0x00007f4475b02a5e in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x00007f44603e35d3 in ReplSemiSyncMaster::commitTrx(char const*, unsigned long long) () from /usr/local/mysql/lib/plugin/semisync_master.so
#2  0x0000000000c8197a in Binlog_storage_delegate::after_sync(THD*, char const*, unsigned long long) ()
#3  0x0000000000edd46b in call_after_sync_hook(THD*) ()
#4  0x0000000000eed935 in MYSQL_BIN_LOG::ordered_commit(THD*, bool, bool) ()
#5  0x0000000000eedf55 in MYSQL_BIN_LOG::commit(THD*, bool) ()
#6  0x000000000081e494 in ha_commit_trans(THD*, bool, bool) ()
#7  0x0000000000dce032 in trans_commit_stmt(THD*) ()
#8  0x0000000000d134e7 in mysql_execute_command(THD*, bool) ()
等待LOCK_commit mutex線程
Thread 6 (Thread 0x7f4460769700 (LWP 25017)):
#0  0x00007f4475b05334 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x00007f4475b0060e in _L_lock_995 () from /lib64/libpthread.so.0
#2  0x00007f4475b00576 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x0000000000eed31f in MYSQL_BIN_LOG::change_stage(THD*, Stage_manager::StageID, THD*, st_mysql_mutex*, st_mysql_mutex*) ()
#4  0x0000000000eed5e8 in MYSQL_BIN_LOG::ordered_commit(THD*, bool, bool) ()
#5  0x0000000000eedf55 in MYSQL_BIN_LOG::commit(THD*, bool) ()
#6  0x000000000081e494 in ha_commit_trans(THD*, bool, bool) ()
#7  0x0000000000dce032 in trans_commit_stmt(THD*) ()
這里就很明顯其他提交事物(這里指的是 Thread 6)堵塞在了MYSQL_BIN_LOG::change_stage函數上,其作用正是獲取某個階段的Mutex。而本線程(這里指的是 Thread 7)則是在ReplSemiSyncMaster::commitTrx上堵塞在某個Mutex上。


五、after_commit和after_sync的代碼位置和區(qū)別


這里直接用代碼說明進行給出,當然我只是提取了說明問題的代碼片段:


commit階段:
1、 change_stage(thd, Stage_manager::COMMIT_STAGE,final_queue, leave_mutex_before_commit_stage,&LOCK_commit))//持有LOCK_commit mutext進入commit階段
2、 sync_error= call_after_sync_hook(commit_queue);//這里調用after sync hook 其在LOCK_commit保護下 此時還沒有做引擎層commit
3、 process_commit_stage_queue(thd, commit_queue);//進行引擎層提交操作,具體細節(jié)以后在研究
4、 mysql_mutex_unlock(&LOCK_commit);//這里提交完成解鎖隊列
5、 stage_manager.signal_done(final_queue); //這里喚醒全部本組堵塞在 flush階段的follower線程 分別做提交 但是如果是order commit 提交已經做完 這里什么都不需要做了
6、 (void) finish_commit(thd); //finish_commit會調用 atfer commit hook 其不在LOCK_commit保護下
如果拋開代碼總結如下:


1、leader 持有LOCK_commit 鎖 進入 commit階段。
2、如果是設置after_sync,使用after sync 掛鉤來確認ack 。
3、進行引擎層提交,完成后解鎖LOCK_commit 鎖。
4、喚醒所有 follwer線程。
5、如果設置是after_commit,使用after commit 掛鉤來確認ack 。
這里我們可以清楚的看到,他們的區(qū)別,實際上正如其名字一樣就是說到底在那個步驟進行日志傳輸完成的確認,是在實際引擎層提交之前還是之后,如果是在之前則在mutex LOCK_commit的保護下,如果是在之后則不需要持有LOCK_commit mutex,這也是為什么會出現上面那個堵塞案例的原因。在5.7中默認是after_sync設置為after_sync后顯然更加安全,如果是after_commit極端情況下可能引擎層已經提交完成,事物對主庫可見,但是從庫還沒有傳輸完成如果從庫奔潰可能出現少事物的情況。

感謝各位的閱讀!關于“MySQL 5.7中sync_binlog參數和半同步中after_commit和after_sync的區(qū)別有哪些”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI