天天看點

十七:主庫的DUMP線程(筆記)

DUMP 線程啟動函數調用流程

  • 1、多次select 互動,從庫需要儲存主庫的資訊
  • 2、注冊從庫資訊
  • 3、讀取從庫發送的各種資訊
com_binlog_dump_gtid
   讀取從庫的資訊包括
   - server id
   - 需要讀取的binlog為名字
   - 讀取的位點
   - 從庫GTID
   - kill_zombie_dump_threads 殺掉本從庫以前的DUMP線程 根據UUID和SERVER_ID聯合判斷
   - mysql_binlog_send
     - Binlog_sender sender 将讀取的資訊儲存
     - sender.run()
       - Binlog_sender::init 初始化檢測
         - 主庫binlog 沒開不允許連接配接 報錯
           "Binary log is not open"
         - 如果master server id為0是不允許連接配接的報錯
           "Misconfigured master - master server_id is 0"
         - 如果GITD協定下GITD_MODE主庫必須為ON,否則報錯
           The replication sender thread cannot start in "
           "AUTO_POSITION mode: this server has GTID_MODE = %.192s "
           "instead of ON.
         - Binlog_sender::check_start_file() 進行從庫GTID值是否可行的判斷,并且打開檔案也就是确認binary log的檔案  
           - 取出從庫關于主庫server_uuid的 GTID是小于等于 主庫的GTID 如果不是則報錯
             簡單的說就是從庫比主庫多事物了。
             比如主庫 1:1-20 2:1-10  從庫:1:1-15 2:1-30 判斷1-15是否小于等于1-20  
             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."             
           - 判斷主庫的主庫的GTID_PURGED是否是從庫GTID的子集 不是則報錯
             簡單的說就是主庫已經清理了從庫拉取需要的GTID。
             比如主庫GTID_PURGED:1:1-10 2:1-5 從庫 1:1-10  因為從庫還需要2:1-5 這些GTID 主庫已經沒有了
             報錯
             The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, 
             but the master has purged binary logs containing GTIDs that the slave requires.             
           - 上面的情況還存在一種特殊情況比如主庫手動删除了binary logfile。這種情況GTID_PURGED可能沒有更新需要
             繼續檢查。
             這一步涉及到實際的binlog掃描。先掃描最後一個binlog 拿到P_EVENT檢查是否 需要拉取的GTID是否在此之後。
             是就結束,否則檢查上一個binlog檔案 同樣拉取P_EVENT檢查是否 需要拉取的GTID是否在此之後,如果延遲較高
             并且設定了relay log reocvery參數的話這個過程可能有些長,比如幾十秒。判斷方式就是拉取P_EVENT來 判斷是
             否是需要的GTID的子集,正常情況這一步還是很快的。如果最後也沒找到則同樣報錯,以前有朋友問我這一步是否
             能夠省略這裡知道這一步是不能省略的原因就是前面說的GTID_PURGED可能不準,并且後面要需要打開這個binlog作為
             掃描的起點binlog
               The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1,         
               but the master has purged binary logs containing GTIDs that the slave requires.                 
          - 将檔案存入 LOG_INFO m_linfo; 中 測試打開這個 binlog 檔案
          
       進入循環  會不斷的讀取下一個檔案,如果不是曆史binary log 
       是目前檔案binary log則會堵塞在send_binlog 會不斷的讀取下,
       這一層循環是循環的binary log檔案
       一個檔案,如果不是曆史binary log 是當然binary log則會堵塞
       - open_binlog_file   打開檔案初始化讀取緩存 IO_CACHE  初始化CACHE 為讀CACHE 大小為8K 檔案指向相應的binary log    
       - Binlog_sender::send_binlog 
         - 從初始化的位點開始讀取
         - get_binlog_end_pos  擷取binary log的最後位置,如果是目前binary log則堵塞擷取 并且發送心跳EVENT
           擷取目前讀取的位置
           進入循環 
           擷取目前bianry log的最後位點
           - 如果不是目前binary log
             擷取需要讀取binary log的最後位置
             如果(log_pos == end_pos)
             讀取到檔案尾部傳回0
             否則傳回最後位置
           - 如果是目前binary log
             wait_new_events(log_pos) 等待新 event的到來 
              進入狀态 sending all event
               - wait_with_heartbeat
                 主要邏輯就是通過 &update_cond, &LOCK_binlog_end_pos來完成
                 如果沒有新的event則 循環等待心跳m_heartbeat_period的描述
                 然後發一個心跳event 給從庫 攜帶目前binlog的位置。
                 如果有break 退出循環了return 1
                 pthread_cond_timedwait 實作 有興趣可以看看這裡的實作。
                 主要在于函數被信号喚醒傳回0 如果是逾時為etimeout。
         - send_events 發送相應位置的 binlog 給從庫
           while循環 為讀取相應位置的binlog event 
           - 擷取EVENT的TYPE 
           - 檢查
             - 如果是auto_position=ON不能有匿名event的存在 如果有則報錯
               Cannot replicate anonymous transaction when AUTO_POSITION = 1, at file %.512s, position %lld.
             - 如果是GTID_MODE=ON不能有匿名event 存在 否則報錯
               Cannot replicate anonymous transaction when @@GLOBAL.GTID_MODE = ON, at file %.512s, position %lld
             - 如果是GITD_MODE=OFF不能有GTID的event存在
               Cannot replicate GTID-transaction when @@GLOBAL.GTID_MODE = OFF, at file %.512s, position %lld
             以上情況實際上如果正常操作是不會出現的,因為每次設定GITD_MODE總是會切換一個binlog,
             但是如果修改GTID_MODE不按照前面提到的流程可能會出現這些錯誤。
             對于第一種錯誤很容易重制,因為auto_postion是start slave初始化傳入的。
             對于第二種和第三種錯誤因為EVENT的
             生成線程和DUMP線程不是同一個線程是異步通知的方式,也就是說生成GTID event到發送這段時間
             如果修改了GTID_MODE可能會出現這些問題。
           - 上面隻是取到file name,POS 是從從庫的master info 傳送過來,
             這種情況下還會過濾掉從庫已經執行的GTID,是以在GTID模式下主庫
             會進行再次過濾。更加安全。
          -  發送event           

繼續閱讀