<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>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                我們看到在MySQL 5.7版本里大量遺留很多年的bug都被fix掉了,bug#12161就是其中一個,該bug在2005年第一次report到Bug list上,十年之后終于在MySQL 5.7.7 第一個RC版本被fix了。 ## Bug描述 當我們顯式開啟一個XA事務,執行操作,并完成XA PREPARE后,如果Kill session或者主動斷開再重連執行XA RECOVER,之前的這個XA事務就會直接丟失掉了。 例如: ~~~ mysql> XA BEGIN 'abc'; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO t1 VALUES (1,2,3); Query OK, 1 row affected (0.00 sec) mysql> XA END 'abc'; Query OK, 0 rows affected (0.00 sec) mysql> XA PREPARE 'abc'; Query OK, 0 rows affected (0.00 sec) mysql> Ctrl-C -- exit! Aborted mysql> XA RECOVER; Empty set (0.00 sec) ~~~ 有趣的是,如果在XA PREPARE后把實例KILL掉,是可以通過XA RECOVER恢復的: ~~~ mysql> XA RECOVER; +----------+--------------+--------------+------+ | formatID | gtrid_length | bqual_length | data | +----------+--------------+--------------+------+ | 1 | 3 | 0 | abc | +----------+--------------+--------------+------+ 1 row in set (0.00 sec) mysql> XA COMMIT 'abc'; Query OK, 0 rows affected (0.00 sec) ~~~ 雖然實例異常重啟可以恢復事務,但引入的另外一個問題是:事務變更的binlog丟失,導致主備數據不一致。 bug產生的原因也很簡單:在退出session時,線程總是會去無條件的回滾掉自己尚未提交的事務。 ## 官方修復 ### 持久化 為了解決這個問題,將XA的兩階段記錄到了Binlog中; 對于上文描述的序列,當執行到XA PREPARE時,記錄第一階段的binlog,如下: ~~~ Query event : XA START X'616263',X'’,1 // 這里的'616262'即是'abc'的十六進制編碼 Table_map event Write_rows event Query event:XA END X'616263',X'',1 XA_prepare event: XA PREPARE X'616263',X'’,1 ~~~ 這時候該XA事務同時在InnoDB層(事務處于Prepare狀態,Redo持久化到磁盤)和Server層都有持久化信息。 其中XA_PREPARE事件是新引入的事件類型(內部類為XA_prepare_event),以后版本升級需要注意到這個低版本不兼容事件。 然后再執行XA COMMIT ‘abc’,產生新的事件: ~~~ Query event:XA COMMIT X'616263',X'',1 ~~~ 如果執行XA ROLLBACK,則記錄: ~~~ Query event:XA ROLLBACK X'616263',X'',1 ~~~ 由于XA PREPARE和XA COMMIT是分開執行的,因此在這兩個事件中間可能存在別的事務,備庫復制線程需要處理這種情況。 為了實現XA PREPARE寫binlog,對binlog_prepare進行了擴展,這里會調用mysql_bin_log.commit, 將cache中的binlog刷到文件中。 Tips:XID可以包含三個部分:gtrid, [, bqual [, format ID]],其中gtrid是必選的,表示全局標識,bqual是分支標識,默認為空’‘,format ID是一個unsigned整型,默認值為1,在上例中,我們只指定了gtrid為’abc’,因此bqual段和format ID均為默認值。更具體的描述參考[官方文檔](http://dev.mysql.com/doc/refman/5.7/en/xa-statements.html)。 ### 如何恢復 當會話斷開時(例如kill session或者一次干凈的shutdown/restart操作),我們必須要能恢復該事務,之前的邏輯是在cleanup時,直接回滾所有的活躍事務。在新版本中,對XA PREPARE的事務做了特殊處理(THD::cleanup),如果處于Prepare狀態,就將事務的in_recovery設置為TRUE,并更新到hash表transaction_cache中(transaction_cache_detach),該hash表用于維護所有XA事務。 對于非XA的活躍事務,在會話斷開時,依然采用回滾策略。 當重連客戶端后,我們可以直接執行 XA COMMIT ‘abc’,這時候會通過XID關鍵字去搜索transaction_cache并將對應的事務提交掉。 同時BINLOG的狀態要保持一致,如果會話斷開前的XA PREPARE沒有記錄Binlog, 重連后執行XA COMMIT也不應該記錄。 ### 備庫復制 由于XA PREPARE和XA COMMIT是分開記錄的,當碰到XA COMMIT時,備庫采用等待之前的事務全部完成,然后再執行的方式(相當于退化到串行)。 另外,我們知道在一個正常的會話過程中,總是為其cache一個事務對象,新的事務會重用這個事務對象,避免多次分配;而XA事務的COMMIT和PREPARE是分離的,需要為XA事務單獨分配事務對象。因此復制線程執行XA START時,將其擁有的事務對象臨時保存起來(detach_native_trx),當執行到XA_prepare_log_event事件時,再將其恢復給復制線程,同時XA事務對象關閉read view,將is_recovered設置為TRUE(函數innodb_replace_trx_in_thd)。 隨后復制線程在執行到XA COMMIT時直接根據XID找到對應的XA事務進行提交。 ## 參考: [WL#6860](http://dev.mysql.com/worklog/task/?id=6860)?Binlogging XA-prepared transaction Github:git show f4c37f7aea732763947980600c6882ec908a54a0 MySQL 5.7.7-RC
                  <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>

                              哎呀哎呀视频在线观看