1. 程式人生 > >MySQL半同步複製--handle_slave_io--5

MySQL半同步複製--handle_slave_io--5

handle_slave_io函式呼叫read_event函式讀取event後,然後呼叫queue_event將讀取的event寫入relay log檔案中。

程式碼如下:

static int queue_event(Master_info* mi,const char* buf, ulong event_len)
{
  int error= 0;
  String error_msg;
  ulong inc_pos= 0;
  Relay_log_info *rli= mi->rli;
  mysql_mutex_t *log_lock= rli->relay_log.get_log_lock();

  char rot_buf[LOG_EVENT_HEADER_LEN + ROTATE_HEADER_LEN + FN_REFLEN];
  Gtid gtid= { 0, 0 };
  Log_event_type event_type= (Log_event_type)buf[EVENT_TYPE_OFFSET];
  ...
  mysql_mutex_lock(&mi->data_lock);
  ...
  switch (event_type) {
  case STOP_EVENT:
    goto err;
  case ROTATE_EVENT:
    Rotate_log_event rev(buf, checksum_alg != BINLOG_CHECKSUM_ALG_OFF ?
                         event_len - BINLOG_CHECKSUM_LEN : event_len,
                         mi->get_mi_description_event());

    process_io_rotate(mi, &rev);
    break;
  case FORMAT_DESCRIPTION_EVENT:
    ...  
    break;
  case HEARTBEAT_LOG_EVENT:
    ...
    break;
  case PREVIOUS_GTIDS_LOG_EVENT:
    ...
    break;
  case GTID_LOG_EVENT:
    ...
    break;
  case ANONYMOUS_GTID_LOG_EVENT:
    
  default:
    inc_pos= event_len;
    break;
  }
  ...
  mysql_mutex_lock(log_lock);
  s_id= uint4korr(buf + SERVER_ID_OFFSET);
  s_id&= opt_server_id_mask;
  if ((s_id == ::server_id && !mi->rli->replicate_same_server_id) ||
      (mi->ignore_server_ids->dynamic_ids.elements > 0 && mi->shall_ignore_server_id(s_id) &&
         (s_id != mi->master_id ||(event_type != FORMAT_DESCRIPTION_EVENT && event_type != ROTATE_EVENT))))
  {
    if (!(s_id == ::server_id && !mi->rli->replicate_same_server_id) ||
        (event_type != FORMAT_DESCRIPTION_EVENT &&
         event_type != ROTATE_EVENT &&
         event_type != STOP_EVENT))
    {
      mi->set_master_log_pos(mi->get_master_log_pos() + inc_pos);
      memcpy(rli->ign_master_log_name_end, mi->get_master_log_name(), FN_REFLEN);
      rli->ign_master_log_pos_end= mi->get_master_log_pos();
    }
    rli->relay_log.signal_update(); // the slave SQL thread needs to re-check
  }
  else
  {
    /* write the event to the relay log */
    rli->relay_log.append_buffer(buf, event_len, mi);
    mi->set_master_log_pos(mi->get_master_log_pos() + inc_pos);//只是更新master的pos,檔名呢?
    rli->relay_log.harvest_bytes_written(&rli->log_space_total);
    ...
  }
  mysql_mutex_unlock(log_lock);

  if (unlock_data_lock)
    mysql_mutex_unlock(&mi->data_lock);

}

bool MYSQL_BIN_LOG::append_buffer(const char* buf, uint len, Master_info *mi)
{
  bool error= false;
  if (my_b_append(&log_file,(uchar*) buf,len) == 0)
  {
    bytes_written += len;
    error= after_append_to_relay_log(mi);
           ->flush_and_sync(0);//relay log滿會rotate
           ->signal_update();
  }
  else
    error= true;
  DBUG_RETURN(error);
}

1、根據事件的各種型別做不同的處理。當接收的是心跳事件時更新最近心跳時間,然後忽略該事件。
當接收到的是ROTATE_EVENT時,說明master的binlog發生變化,需要更新Master_info例項mi中master_log_file和master_log_pos資訊。
2、先獲取relay-log鎖,然後呼叫append_buffer將事件寫入relay-log中。append_buffer函式的功能:
  1)呼叫my_b_append函式將接收的事件寫入relay-log的快取中
  2)after_append_to_relay_log函式會呼叫flush_and_sync,將IO_CACHE內容刷到relay-log並持久化到磁碟
     將事件寫入到relay log後,判斷當前檔案是否達到max_relay_log_size指定大小,如果大就需要進行rotate
  3)呼叫signal_update通知slave sql執行緒relay-log有更新,可以繼續重放動作。

     如果slave也作為master,在其commit時,也是signal_update函式通知master dump函式傳送event;這裡會不會有衝突?

    relay_log類的函式。

  4)由於讀取了主庫的事件,所以要更新mi中的master_log_file和master_log_pos資訊。

相關推薦

MySQL同步複製--handle_slave_io--5

handle_slave_io函式呼叫read_event函式讀取event後,然後呼叫queue_event將讀取的event寫入relay log檔案中。程式碼如下:static int queue_event(Master_info* mi,const char* bu

《深入淺出MySQL:資料庫開發、優化與管理維護(2nd)》第31章之MySQL同步複製搭建學習筆記

MySQL的非同步複製在使用的過程中,主庫和從庫的資料之間存在一定的延遲,這樣存在一個隱患:當在主庫上寫入一個事務並提交成功,而從庫尚未得到主庫推送的Binlog日誌時,主庫宕機了,例如主庫可能因磁碟損壞、記憶體故障等造成主庫上該事務Binlog丟失,此時從庫就可能損失這個事務,從而造成主從不一致。

Mysql 同步複製和非同步複製

mysql 半同步複製和非同步複製 -- 在主庫中安裝半同步外掛,開啟半同步複製功能 install plugin rpl_semi_sync_master soname 'semisync_master.so'; set global rpl_semi_sync_master_enab

MySQL同步複製

MySQL資料庫複製的預設方式是非同步複製,但是非同步複製的不足之處就在於,當主庫把event寫入二進位制日誌之後,並不知道從庫是否已經接收並應用了。在非同步模式的複製,如果主庫崩潰,很有可能在主庫中已經提交的事務,並沒有傳到到任何一臺從庫機器上。在高可用叢集

支援MySQL同步複製的virtual_slave元件

文章目錄 一、簡介 二、新的技術架構 三、virtual_slave 一、簡介 在設計高可用架構時,為了保證主從故障切換時的資料一致性,有各種處理方式。在5.5/5.6的單機房資料庫架構中,我們採取了共享儲存的

MySQL 同步複製+MMM架構

介紹     上篇文章介紹了MMM架構的實現方法,但是上篇文章的MMM方案的複製是非同步複製,非同步複製的主要問題在於當主從存在延時時如果主機出現了故障導致了主從切換時這時將會存在資料丟失;mysql為了解決非同步複製資料丟失的問題增加了半同步複製,半同步複製存在5.5以上的版本,半同步複製的原理是客戶

Mysql同步複製模式說明 - 運維小結

  MySQL主從複製包括非同步模式、半同步模式、GTID模式以及多源複製模式,預設是非同步模式 (如之前詳細介紹的mysql主從複製)。所謂非同步模式指的是MySQL 主伺服器上I/O thread 執行緒將二進位制日誌寫入binlog檔案之後就返回客戶端結果,不會考慮二進位制日誌是否完整傳輸到

Mysql同步複製模式

MySQL主從複製包括非同步模式、半同步模式、GTID模式以及多源複製模式,預設是非同步模式 (如之前詳細介紹的mysql主從複製)。所謂非同步模式指的是MySQL 主伺服器上I/O thread 執行緒將二進位制日誌寫入binlog檔案之後就返回客戶端結果,不會考慮二進位制日誌是否完整傳輸

Mysql同步複製、資料一致性檢查

1:配置非同步複製 scripts/mysql_install_db --user=mysql --datadir=/mysql/data bin/mysqld_safe --user=mysql & 在master上建立複製使用者: mysql> GRANT

MySQL同步複製--transmit_start

介紹半同步複製binlog dump執行緒需要做的事情。相關結構:Binlog_transmit_observer transmit_observer = { sizeof(Binlog_transmit_observer), // len repl_semi_bi

mysql 同步複製(semi_sync_replication)搭建及使用

      google為mysql開發了一個補丁一個基於半同步的補丁,應用與mysql5.0。回來mysql打上了該補丁,並在5.5版本中使用。半同步複製的理念是什麼呢?在資料庫更改操作執行前,確保更改操作至少被寫入一臺slave磁碟中,意味著著對於每一個連線,最多隻有一

MySQL同步複製原理配置與介紹

環境介紹: Ubuntu Server 16.04.2+MySQL 5.7.17 Community Server (GPL) MySQL安裝 1、下載mysql-apt-config_0.8.3-1_all.deb 2、安裝deb

mysql同步複製&組複製&全同步機制

先配置好主從 配置主從詳見上一篇部落格,這裡只是簡單過一邊 mysql> grant replication slave on *.* to 'haha'@'172.25.53.%' identified by '[email protect

mysql同步複製搭建及驗證測試

非同步複製:客戶端提交日誌後,主庫寫入日誌到binlog,即可成功返回給客戶端。 半同步複製:客戶端提交日誌後,主庫寫入日誌到binlog,需等待其中一個slave也接收到binlog事務併成功寫入relay log後,主庫才返回commmit操作成功給客戶端。 如果主庫與

MySQL 5.7的同步複製

環境 角色 IP port master 192.168.80.136 3310 slave 192.168.80.137 3310 master [mysqld] rpl_semi_sync_master_enabled=1 rp

MySQL 5.6 一主多從的 同步複製搭建(已糾正)

# The following options will be passed to all MySQL clients [client] #password       = your_password port            = 3306 socket          = /tmp/my

MySQL同步復制--handle_slave_io等待master發送event

mysql handle_slave_iohandle_slave_io函數調用read_event函數:read_event函數從連接中讀取事件,如果沒有事件將會阻塞在這裏等待master發送事件。#0 0x00898402 in __kernel_vsyscall () #1 0x00c28133 i

mysql GTID 同步複製

1)什麼是GTID GTID(Global Transaction ID)是對於一個已提交事務的編號,並且是一個全域性唯一的編號。GTID實際上是由UUID+TID組成的。其中UUID是一個MySQL例項的唯一標 識,儲存在mysql資料目錄下的auto.cnf檔案裡。TID代表了該例項上已經提交的事務數量

MySQL主從複製,並行複製同步複製和組複製

主從複製 主從複製過程存在三個執行緒,Master端的I/O執行緒,Slave的I/O執行緒與SQL執行緒。Master端需要開啟binlog日誌,Slave端需要開啟relaylog。 1、Slave端的I/O讀取master.info檔案,獲取binlog檔名和位置點,然後向Mast

MySQL高可用方案 MHA之四 keepalived 同步複製

    [[email protected] ~]# cat /etc/mysql_mha/app1.cnf [server default]manager_log=/data/mysql_mha/app1-manager.logmanager_workdir=/data/m