<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## bug背景 官方 5.7.6 版本對 gtid 有非常多的改進和bugfix,其中有一個 bugfix 是針對 relay log 中沒有接收完整的 gtid 事務的。正常的relay log 中的 gtid 事務應該是像下面這樣: 1\. gtid event 2\. query event (begin) 3\. row event (write/update/delete) 4\. query event (commit) 上面這 4 個 event 序列構成一個 group。因為 IO 線程從主庫接收 binlog 時,是以 event 為單位的,如果在 group 中間,比如3之后,stop slave 停掉IO線程的話,relay log 中就會記錄一個不完整的事務。我們知道,GTID 的 auto_position 協議是通過計算主備庫之間 GTID 集合的差集,然后來確定哪些 binlog 是要從主發給備的,備庫用的集合就是 Retrieved_Gtid_Set 和 gtid_executed 的并集。IO 線程收到一個 gtid event 就會把它加入到 Retrieved_Gtid_Set 中,所以如果這個時候 start slave的話,最后這個不完整的事務是不會重新發送的,因為根據協議,主庫認為備庫已經有了這個事務,不需要再發送了。 ## 修復分析 之所以會出現這種問題,是因為 IO 線程在處理的時候,沒有將 gtid_event 和后面的事件序列當作一個整體來看待,只要收到開頭的 gtid event,就認為整個 group 都已經收到。 所以官方的修復就是加一個事務邊界檢查器(Transaction_boundary_parser),只有當 IO 線程收到完整的 group,才將 gtid 加入到 Retrieved_Gtid_Set;同樣在 mysqld 重啟從 relay log 中初始化 Retrieved_Gtid_Set 時,也利用邊界檢查器判斷 realy log 中的 gtid 事務是否完整。 下面就看下這個邊界檢查器是如何做判斷的: 將 relay log 中的 event 序列分為2種,DDL 和 DML。 ~~~ DDL 序列如下: DDL-1: GTID event DDL-2: User_var/Intvar/Rand event DDL-3: Query event DML 序列如下: DML-1: GTID event DML-2: Query event(BEGIN) DML-3: Query event(除了 BEGIN/COMMIT/ROLLBACK) / Rows event / load event) DML-4: (Query event (COMMIT) | Query event(ROLLBACK) | Xid) ~~~ 然后定義了5種狀態,標識目前讀到的 event 事件是在事務內還是事務外。 1\. EVENT_PARSER_NONE // 在事務外,這個時候應該是讀完 DDL-3 或者 DML-4 2\. EVENT_PARSER_GTID // 讀到了GTID event,處于事務中,這個時候應該是讀到 DDL-1 或者 DDL-3 3\. EVENT_PARSER_DDL // 處于事務中,讀到 DDL-2 4\. EVENT_PARSER_DML // 處于事務中,讀到 DML-2 或者 DML-3 5\. EVENT_PARSER_ERROR // 錯誤狀態 邊界檢查器的實現是一個狀態機,根據目前所處的狀態和讀到的event,確定下一步應該轉移到什么狀態。 比如對于下面這樣的 event 序列: 1\. gtid 2\. begin 3\. update rows 4\. commit 狀態是這樣轉移的,剛開始是 EVENT_PARSER_NONE,讀到事件1,轉為 EVENT_PARSER_GTID 狀態,讀到事件2,轉為 EVENT_PARSER_DML 狀態,讀到事件3,轉為EVENT_PARSER_DML狀態,讀到事件4,轉為 EVENT_PARSER_NONE 狀態。從EVENT_PARSER_NONE(事務外)最終又到 EVENT_PARSER_NONE,中間讀了一個完整的事務。 詳細的狀態轉移規則可以看[官方patch](https://github.com/mysql/mysql-server/commit/9dab9dad975d09b8f37f33bf3c522d36fdf1d0f9 "SHOW SLAVE STATUS/RETRIEVED_GTID_SET MAY HAVE PARTIAL TRX OR MISS COMPLETE TRX")。 有了這個邊界檢測器后,IO 線程就能準確判斷當前是處于事務外還是事務內,從而決定要不要把GTID添加到 Retrieved_Gtid_Set 中。 ## 相關bug 對于 relay log 部分事務的問題,官方[之前有個patch](https://github.com/mysql/mysql-server/commit/e7a4cbe6a6449989e483d46abe79169f717a0725 "TRANSACTIONS SKIPPED ON SLAVE AFTER \"STOP/START SLAVE\" USING GTID REPLICATION"),其邏輯是對 relay log 中最后一個 gtid 做特殊處理。在 request dump 的時候,如果這個 gtid 不在備庫的 gtid_executed 集合中的話,就把這個 gtid 從發送給主庫的 gtid 集合里去掉,這樣主庫就會把這個最后的 gtid 事務重新發過來;如果這個 gtid 已經在備庫的 gtid_executed 集合中的話,就不從發送給主庫的 gtid 集合里去掉,這樣主庫庫就不會重發。 但是這種修復方式依賴于 gtid_executed,并不是根據事務是否完整來決定要不要重拉事務,所以有的場景下會有問題,如?[bug#72392](https://bugs.mysql.com/bug.php?id=72392 "inconsistent data in GTID (reset master, stop slave, start slave)")?這種場景。 官方目前這種用邊界檢測的修復方式是比較好的,但是可能會有性能上的問題,因為每個的 event 都要用邊界檢查器判斷下,像 query event 需要要進行字符串比較。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看