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

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                繼上兩期月報,MySQL5.7新特性之一介紹了一些新特性及兼容性問題,MySQL 5.7新特性之二介紹了臨時表的優化和實現。? 這期我們一起來學習下undo空間管理,重點介紹truncate功能。 ### 1\. 背景 InnoDB存儲引擎中,undo在完成事務回滾和MVCC之后,就可以purge掉了,但undo在事務執行過程中,進行的空間分配如何回收,就變成了一個問題。 我們親歷用戶的小實例,因為一個大事務,導致ibdata file到800G大小。 我們先大致看下InnoDB的undo在不同的版本上的一些演進: MySQL 5.5的版本上? InnoDB undo是放在系統表空間即ibdata file文件中,這樣如果有比較大的事務(即需要生成大量undo的),會撐大ibdata數據文件, 雖然空間可以重用, 但文件大小不能更改。? 關于回滾段的,只有這個主要的參數,用來設置多少個rollback segment。 ~~~ mysql> show global variables like '%rollback_segment%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | innodb_rollback_segments | 128 | +----------------------------+-------+ ~~~ MySQL 5.6的版本上? InnoDB undo支持獨立表空間, 增加如下參數: ~~~ +-------------------------+-------+ | Variable_name | Value | +-------------------------+-------+ | innodb_undo_directory | . | | innodb_undo_logs | 128 | | innodb_undo_tablespaces | 1 | +-------------------------+-------+ ~~~ 這樣,在install的時候,就會在data目錄下增加undo數據文件,來組成undo獨立表空間,但文件變大之后的空間回收還是成為問題。 MySQL 5.7的版本上? InnoDB undo在支持獨立表空間的基礎上,支持表空間的truncate功能,增加了如下參數: ~~~ mysql> show global variables like '%undo%'; +--------------------------+------------+ | Variable_name | Value | +--------------------------+------------+ | innodb_max_undo_log_size | 1073741824 | | innodb_undo_directory | ./ | | innodb_undo_log_truncate | OFF | | innodb_undo_logs | 128 | | innodb_undo_tablespaces | 3 | +--------------------------+------------+ mysql> show global variables like '%truncate%'; +--------------------------------------+-------+ | Variable_name | Value | +--------------------------------------+-------+ | innodb_purge_rseg_truncate_frequency | 128 | | innodb_undo_log_truncate | OFF | +--------------------------------------+-------+ ~~~ InnoDB的purge線程,會根據innodb_undo_log_truncate開關的設置,和innodb_max_undo_log_size設置的文件大小閾值,以及truncate的頻率來進行空間回收和rollback segment的重新初始化。 接下來我們詳細看下5.7的InnoDB undo的管理: ### 2\. undo表空間創建 設置innodb_undo_tablespaces的個數, 在mysql install的時候,創建指定數量的表空間。? InnoDB支持128個undo logs,這里特別說明下,從5.7開始,innodb_rollback_segments的名字改成了innodb_undo_logs,但表示的都是回滾段的個數。? 從5.7.2開始,其中32個undo logs為臨時表的事務分配的,因為這部分undo不記錄redo,不需要recovery,另外從33-128一共96個是redo-enabled undo。 rollback segment的分配如下: ~~~ Slot-0: reserved for system-tablespace. Slot-1....Slot-N: reserved for temp-tablespace. Slot-N+1....Slot-127: reserved for system/undo-tablespace. */ ~~~ 其中如果是臨時表的事務,需要分配兩個undo logs,其中一個是non-redo undo logs;這部分用于臨時表數據的回滾。 另外一個是redo-enabled undo log,是為臨時表的元數據準備的,需要recovery。 而且, 其中32個rollback segment創建在臨時表空間中,并且臨時表空間中的回滾段在每次server start的時候,需要重建。 每一個rollback segment可以分配1024個slot,也就是可以支持96*1024個并發的事務同時, 但如果是臨時表的事務,需要占用兩個slot。 InnoDB undo的空間管理簡圖如下: ![](https://box.kancloud.cn/2016-07-22_5791a6c6be767.jpg) 注核心結構說明: 1\. rseg slot? rseg slot一共128個,保存在ibdata系統表空間中,其位置在: ~~~ /*!< the start of the array of rollback segment specification slots */ #define TRX_SYS_RSEGS (8 + FSEG_HEADER_SIZE) ~~~ 每一個slot保存著rollback segment header的位置。包括space_id + page_no,占用8個bytes。其宏定義: ~~~ /* Rollback segment specification slot offsets */ /*-------------------------------------------------------------*/ #define TRX_SYS_RSEG_SPACE 0 /* space where the segment header is placed; starting with MySQL/InnoDB 5.1.7, this is UNIV_UNDEFINED if the slot is unused */ #define TRX_SYS_RSEG_PAGE_NO 4 /* page number where the segment header is placed; this is FIL_NULL if the slot is unused */ /* Size of a rollback segment specification slot */ #define TRX_SYS_RSEG_SLOT_SIZE 8 ~~~ 2\. rseg header? rseg header在undo表空間中,每一個rseg包括1024個undo segment slot,每一個slot保存著undo segment header的位置,包括page_no,暫用4個bytes,因為undo segment不會跨表空間,所以space_id就沒有必要了。? 其宏定義如下: ~~~ /* Undo log segment slot in a rollback segment header */ /*-------------------------------------------------------------*/ #define TRX_RSEG_SLOT_PAGE_NO 0 /* Page number of the header page of an undo log segment */ /*-------------------------------------------------------------*/ /* Slot size */ #define TRX_RSEG_SLOT_SIZE 4 ~~~ 3\. undo segment header? undo segment header page即段內的第一個undo page,其中包括四個比較重要的結構: | undo segment header | 進行段內空間的管理 | |---|---|---| | undo page header | page內空間的管理,page的類型:FIL_PAGE_UNDO_LOG | | undo header | 包含undo record的鏈表,以便安裝事務的反順序,進行回滾 | | undo record | 剩下的就是undo記錄了。 | ### 3\. undo段的分配 undo段的分配比較簡單,其過程如下: 首先是rollback segment的分配: ~~~ trx->rsegs.m_redo.rseg = trx_assign_rseg_low( srv_undo_logs, srv_undo_tablespaces, TRX_RSEG_TYPE_REDO); ~~~ 1. 使用round-robin的方式來分配rollback segment 2. 如果有單獨設置undo表空間,就不使用system表空間中的undo segment 3. 如果設置的是truncate的就不分配 4. 一旦分配了,就設置trx_ref_count,不允許truncate。 具體代碼參考: ~~~ /******************************************************************//** Get next redo rollback segment. (Segment are assigned in round-robin fashion). @return assigned rollback segment instance */ static trx_rseg_t* get_next_redo_rseg( /*===============*/ ulong max_undo_logs, /*!< in: maximum number of UNDO logs to use */ ulint n_tablespaces) /*!< in: number of rollback tablespaces */ ~~~ 其次是undo segment的創建: 從rollback segment里邊選擇一個free的slot,如果沒有,就會報錯,通常是并發的事務太多。? 錯誤日志如下: ~~~ ib::warn() << "Cannot find a free slot for an undo log. Do" " you have too many active transactions running" " concurrently?"; ~~~ 如果有free,就創建一個undo的segment。 核心的代碼如下: ~~~ /***************************************************************//** Creates a new undo log segment in file. @return DB_SUCCESS if page creation OK possible error codes are: DB_TOO_MANY_CONCURRENT_TRXS DB_OUT_OF_FILE_SPACE */ static dberr_t trx_undo_seg_create( /*================*/ trx_rseg_t* rseg __attribute__((unused)),/*!< in: rollback segment */ trx_rsegf_t* rseg_hdr,/*!< in: rollback segment header, page x-latched */ ulint type, /*!< in: type of the segment: TRX_UNDO_INSERT or TRX_UNDO_UPDATE */ ulint* id, /*!< out: slot index within rseg header */ page_t** undo_page, /*!< out: segment header page x-latched, NULL if there was an error */ mtr_t* mtr) /*!< in: mtr */ /* fputs(type == TRX_UNDO_INSERT ? "Creating insert undo log segment\n" : "Creating update undo log segment\n", stderr); */ slot_no = trx_rsegf_undo_find_free(rseg_hdr, mtr); if (slot_no == ULINT_UNDEFINED) { ib::warn() << "Cannot find a free slot for an undo log. Do" " you have too many active transactions running" " concurrently?"; return(DB_TOO_MANY_CONCURRENT_TRXS); } ~~~ ### 4\. undo的truncate undo的truncate主要由下面兩個參數控制:innodb_purge_rseg_truncate_frequency,innodb_undo_log_truncate。? 1\. innodb_undo_log_truncate是開關參數。? 2\. innodb_purge_rseg_truncate_frequency默認128,表示purge undo輪詢128次后,進行一次undo的truncate。 當設置innodb_undo_log_truncate=ON的時候, undo表空間的文件大小,如果超過了innodb_max_undo_log_size, 就會被truncate到初始大小,但有一個前提,就是表空間中的undo不再被使用。 其主要步驟如下: 1\. 超過大小了之后,會被mark truncation,一次會選擇一個 2\. 選擇的undo不能再分配新給新的事務 3\. purge線程清理不再需要的rollback segment 4\. 等所有的回滾段都釋放了后,truncate操作,使其成為install db時的初始狀態。 默認情況下, 是purge觸發128次之后,進行一次rollback segment的free操作,然后如果全部free就進行一個truncate。 但mark的操作需要幾個依賴條件需要滿足: 1\. 系統至少得有兩個undo表空間,防止一個offline后,至少另外一個還能工作 2\. 除了ibdata里的segment,還至少有兩個segment可用 3\. undo表空間的大小確實超過了設置的閾值 其核心代碼參考: ~~~ /** Iterate over all the UNDO tablespaces and check if any of the UNDO tablespace qualifies for TRUNCATE (size > threshold). @param[in,out] undo_trunc undo truncate tracker */ static void trx_purge_mark_undo_for_truncate( undo::Truncate* undo_trunc) ~~~ 因為,只要你設置了truncate = on,MySQL就盡可能的幫你去truncate所有的undo表空間,所以它會循環的把undo表空間加入到mark列表中。 最后,循環所有的undo段,如果所屬的表空間是marked truncate,就把這個rseg標志位不可分配,加入到trunc隊列中,在purge的時候,進行free rollback segment。 注意:? 如果是在線庫,要注意影響,因為當一個undo tablespace在進行truncate的時候,不再承擔undo的分配。只能由剩下的undo 表空間的rollback segment接受事務undo空間請求。 MySQL 5.7 新特性系列,下次進行group replication的分享,敬請期待。
                  <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>

                              哎呀哎呀视频在线观看