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

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 背景 最近在Aliyun RDS的環境上,有些用戶碰到了打開文件句柄數過多的錯誤,查看用戶實例的打開句柄個數,確實超過了系統設置的值,一旦出現了這種錯誤,將會帶來連鎖的各種錯誤(取決于當時正在操作什么類型的文件,以及什么操作)。下面,我們就一起來看一下MySQL在操作過程中,牽涉到文件打開和關閉的關鍵點,以及你一直以來可能存在的認識誤區。 ## 參數和名詞 關聯參數 我們先列一下幾個關鍵的參數,不了解的可以先參考官方文檔,我們假設在MySQL 5.6版本上,主要針對InnoDB表。 ~~~ open_file_limits table_open_cache table_definition_cache innodb_file_per_table innodb_open_files ~~~ open_file_limits的設置的值,mysqld會通過setrlimit系統調用來初始化本進程可以使用的最大文件句柄數。 而另外的四個參數的設置,對打開的文件數產生什么影響?我們稍后分析。 關聯名詞 下面列出的名稱,是在MySQL源代碼中出現的,能幫助我們更好的理解參數的設置: * table:MySQL操作一張表時建的對象,table_open_cache參數控制緩存的對象就是table; * table_share:MySQL對一張表的定義建的對象, table_definition_cache參數控制緩存的對象就是table_share; * handler:引擎句柄,和table是一對一的關系,每一種引擎都實現自己的handler,這也是MySQL支持多引擎的關鍵; * innobase_share:InnoDB引擎層對應的表定義對象; * dict_table:InnoDB引擎對應的表結構定義; * fil_tablespace:InnoDB引擎層對應的表空間,當設置innodb_file_per_table=ON的時候,每一個InnoDB表對應一個表空間; * fil_node:表空間對應的節點,如果一個表空間對應多個文件,比如logfile,那么就tablespace和node就是一對多的關系。 對照著上面提到的參數和名稱,下面來看幾個場景。 ## 3\. 場景 我們把一個簡單的select語句在MySQL中的操作分為三個過程,open/read/close。 open過程 當操作某張表的時候,比如select * from test; 1. 首先初始化一個table_share對象: * 如果對象在table_definition_cache中存在,就直接引用; * 如果不存在,就打開test.frm,讀取表結構的定義,創建table_share對象,然后就關閉了test.frm。所以,這一步只在table_definition_cache未命中的時候,才open/close frm文件,并不占用太久的句柄。 2. 然后創建table對象: * 如果在table_open_cache中存在unused_table, 就直接使用; * 如果不存在,就會創建table對象,這里并不牽涉到文件操作。 server層所需要的對象已經創建完畢,下面是InnoDB層: 1. 首先創建InnoDB handler 和Innobase_share 對象,這一步僅僅是內存對象,不牽涉文件操作。 2. 然后load dict_table對象: * 如果在dictionary cache中存在dict_table,就直接引用; * 如果不存在,InnoDB會讀取系統表空間(ibdata)的SYS_TABLES表,讀取InnoDB記錄的表結構定義,同時還會讀取SYS_INDEXES, SYS_COLUMN, SYS_FOREIGN 等和表關聯的定義。 注:這里會牽涉到數據字典的讀取操作,但因為ibdata文件從系統啟動的時候,就一直處在打開狀態,并且不能關閉,所以這里也沒有打開新的文件操作。 3. 最后load test表空間,在fil_system的緩存中查找: 如果存在,就直接使用,如果不存在,會讀取SYS_DATAFILES系統字典表,并打開第一個文件,這里只有一個文件test.ibd,讀取segment header驗證space id,驗證成功,就創建了file_tablespace和fil_node對象。 注:這里會打開test.ibd文件,驗證完tablespace id就會關閉。 結論 這里我們發現,在讀取一張表的之前的open過程,雖然有open file的動作,但都是用于初始化定義、結構等信息。所以table_open_cache, table_definition_cache并不會對open_file_limits有什么影響。而innodb_file_per_table的設置,只是增加了open file超過limit的幾率,并不會有直接的影響。 read 過程 open完成后,當select需要掃描BTree結構上的某一個leaf page,而buffer pool未命中的時候,會發起IO操作: InnoDB會通過fil_node對象里的file handler進行IO操作,但這里每次open file的時候,會進行innodb_open_files判斷。如果當前InnoDB打開的文件數超過了innodb_open_files,就會強制關閉一些文件,在fil_system全局結構中有一個LRU鏈表,這里保存了所有打開的用戶表空間文件句柄,并且當前沒有任何IO操作。系統可以安全的關閉一些文件句柄,以滿足innodb_open_files的需要。 結論 對于InnoDB來說,innodb_open_files設置了一個安全的file limit,除非InnoDB發起的并發IO請求數過多,并且分散在不同的表空間上。 close過程 當語句完成后,會進行close動作: 1. 如果當前table cache大小沒有超過table_open_cache,就把table緩存到cache中; 2. 如果table_share的ref_count,就是table引用次數減到0,說明沒有table引用,并且超過了table_definition_cache,就從cache中刪除; 3. 同樣,innobase_share也根據ref_count來判斷是否要緩存。InnoDB層的dict_table也緩存在dictionary cache中。 結論 close的過程,并沒有文件的關閉動作,而僅僅是內存對象的緩存或者銷毀的動作。 總體來看這三個過程:InnoDB所有和文件相關的對象、fil_tablespace、fil_node和語句、事務等一些生命周期并沒有什么關系。所以語句的并發,事務的大小等等因素都不會引起文件打開數過多。 recovery過程 recovery的過程中,因為無法判斷要應用的redo,所以會load fil_space一遍,會打開所有的ibd文件一遍,進行一次讀取。但同樣受限innodb_open_files的控制,同時打開文件數不能超過這個值。 不過5.7已經添加了一種新的redo類型MLOG_FILE_NAME ,來[優化recovery的過程](http://mysqlserverteam.com/innodb-crash-recovery-improvements-in-mysql-5-7/)。 系統啟動 在系統啟動的過程中,會初始化ibdata和logfile文件,這兩類文件,是永久打開的,不受innodb_open_files限制,但數量有限。 從上面來看,InnoDB并不會引起這么明顯的open files過多的問題,那問題究竟出現在哪里? ## 問題 在MySQL實例中還存在其他文件,比如用戶連接創建的socket、binlog 文件、relay log文件、slow log等log文件。socket由max_connections來控制,log文件的打開數量有限。所以問題回到了MyISAM表上面,對于用戶創建的MyISAM分區表,open的過程中,會把MYD文件全部打開,當分區過多的時候,open files數量就急劇上升,導致超過limit值。 ## flush table會關閉打開的文件嗎? flush table操作,會把table cache中未使用的table close掉,前面我們看到close的操作,并不會產生文件關閉操作。不過MyISAM實現的handler的close函數,會把打開的文件句柄給關閉掉,所以flush table能夠緩解open files過多的問題,但僅限于MyISAM,而InnoDB的文件打開/關閉邏輯并不受影響。 ## 總結 所以,對于用戶實例的open file limit的設置問題,需要計算好連接數、系統文件、表文件等文件,另外建議使用InnoDB表來避免open files 暴漲的問題。
                  <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>

                              哎呀哎呀视频在线观看