探索MYSQL開啟大頁記憶體

zengmuansha發表於2024-03-01

1 開啟大頁記憶體的好處:

1.減少記憶體置換

2.減少TLB miss次數

3.減少swap
4 避免被系統OOM KILL 掉


2 在開啟MYSQL8 時系統記憶體使用情況

mysql> system  free -m

              total        used        free      shared  buff/cache   available

Mem:           7821        5884        1225          14         711        1239

Swap:          8063          25        8038


-- 此時系統頁表 15.5MB


mysql> system cat /proc/meminfo |grep PageTable

PageTables:        15888 kB


關閉MYSQL後頁表大小和記憶體大小

PageTables:         4076 kB



[root@localhost ~]# free -m

              total        used        free      shared  buff/cache   available

Mem:           7821         202        6917          15         701        6920

Swap:          8063          25        8038


MYSQL 佔用了11812KB的系統頁表,對應記憶體5884-202=5480MB


 3 計算需要多少 huge pages

啟用 huge page之前 首先我們要計算分配多少huge page給mysql 使用。

一般的建議是mysql使用的總記憶體大小加上10%。計算公式如下

    S = (table_open_cache + innodb_buffer_pool_size + innodb_log_file_size + performance_schema.memory) + 10 %INNODB BUF 4096MB+LOG BUF 16MB+BINLOG CACHE 16MB + ..=4160 /2MB =2080頁 *1.1=2288=2290


      SELECTROUND(@@table_open_cache/1024/1024,2) as TABLE_OPEN_MB,ROUND(@@innodb_buffer_pool_size/1024/1024,2) as BUF_POOL ,ROUND(@@innodb_log_buffer_size/1024/1024,2) as LOG_BUF,ROUND(@@binlog_cache_size/1024/1024,2) as BINLOG_CACHE,ROUND(@@tmp_table_size/1024/1024,2) as TMP_TABLE,ROUND(@@max_heap_table_size/1024/1024,2) as HEAP_TABLE_MEM;


      4 系統設定

       

      1 動態設定分配大頁記憶體:

      echo 2290 > /proc/sys/vm/nr_hugepages


      #此時系統記憶體狀態大頁記憶體已被使用.

      [root@localhost ~]# free -m

                    total        used        free      shared  buff/cache   available

      Mem:           7821        4784        2305          15         730        2338

      Swap:          8063          25        8038



      #系統記憶體資訊 大頁記憶體裡面分配還未使用中

      cat /proc/meminfo

      PageTables:         4088 kB

      HugePages_Total:    2290

      HugePages_Free:     2290

      HugePages_Rsvd:        0

      HugePages_Surp:        0

      Hugepagesize:       2048 kB


      2 透過 id mysql 獲取mysql所在的group id

      [root@localhost ~]# id mysql

      uid=27(mysql) gid=27(mysql) groups=27(mysql)


      echo 27 > /proc/sys/vm/hugetlb_shm_group


      [root@localhost ~]#  sysctl -w vm.hugetlb_shm_group=27

      vm.hugetlb_shm_group = 27


      3 配置核心引數

      設定核心引數kernel.shmmax和kernel.shmall

      shmmax是最大的共享記憶體段的大小,單位是位元組,預設32M

      shmall是共享記憶體的總大小,單位是頁 

      cat /etc/sysctl.conf

      #-- kernel.shmmni這個核心引數用於設定系統範圍內共享記憶體段的最大數量。該引數的預設值是 4096.

      #-- kernel.shmall 控制共享記憶體頁數  

      #-- kernel.shmmax 單個共享記憶體段的最大尺寸,設定為實體記憶體的 50%

      #-- Increase total amount of shared memory.  The value

      #-- is the number of pages. At 4KB/page, 4194304 = 16GB.

      #--echo 4194304 > /proc/sys/kernel/shmall

      #--對於mysql的使用,最好是shmmax與shmall接近

      #--7168MB


      kernel.shmmax = 7516192768

      kernel.shmall = 1835008  

      kernel.shmmni = 4096



      vm.hugetlb_shm_group =27 #--MYSQL 所在的使用者組ID

      vm.nr_hugepages=2290      ##--持久化大頁記憶體數量


      4.修改ulimit

        vim /etc/security/limits.conf

      @mysql soft memlock unlimited

      @mysql hard memlock unlimited


      使用ulimit -l或設定/etc/security/limits.conf


      5  配置 my.cnf

      [mysqld]

      large-pages


        
        
        #Global Memon Set######  4096MB, binlog_cache=16MB;logbuf=16MB
        
        innodb_buffer_pool_size=4294967296
        
        binlog_cache_size=16777216
        
        innodb_log_buffer_size=16777216
        
        innodb_buffer_pool_dump_at_shutdown = OFF
        
        innodb_buffer_pool_load_at_startup  = OFF
        
        large-pages
        
        
        #locked_in_memory=YES
        
        
        #### Thread Memon Set
        
        join_buffer_size=8388608
        
        sort_buffer_size=8388608
        
        read_buffer_size=8388608
        
        read_rnd_buffer_size=8388608
        
        tmp_table_size=16777216
        
        
        #
        
        bulk_insert_buffer_size=8388608
        
        thread_cache_size                  = 32
        
        thread_stack                       = 256K
        
        
        

        (9) 啟動mysqld



        6 觀察HugePages 使用情況


        [root@localhost ~]# free -m

                      total        used        free      shared  buff/cache   available

        Mem:           7821        4784        2305          15         731        2338

        Swap:          8063          25        8038

        [root@localhost ~]# cat /proc/meminfo | grep Page

        AnonPages:         66604 kB

        PageTables:         4076 kB

        AnonHugePages:         0 kB

        HugePages_Total:    2290

        HugePages_Free:     2290

        HugePages_Rsvd:        0

        HugePages_Surp:        0


        [root@localhost ~]# service mysqld start

        Redirecting to /bin/systemctl start mysqld.service


        [root@localhost ~]# cat /proc/meminfo | grep Page

        AnonPages:        406744 kB

        PageTables:         5296 kB

        AnonHugePages:         0 kB

        HugePages_Total:    2290

        HugePages_Free:     2217

        HugePages_Rsvd:     2039

        HugePages_Surp:        0


        [root@localhost ~]# free -m

                      total        used        free      shared  buff/cache   available

        Mem:           7821        5117        1972          15         731        2005

        Swap:          8063          25        8038



        結果還是使用部分大頁記憶體 2290-2217 =146MB

        傳統頁 5117-4784=333MB

        MYSQL使用了333M記憶體,其中146MB使用了大頁記憶體,另外187MB使用傳統記憶體.

        哎呀 這是為啥呢? 使用一部分大頁記憶體,又使用一部分傳統頁記憶體,

        大頁記憶體還保留2039 大約 4078 這應該是INNODB BUF大小

         

        這個是MYSQL 8.0.25 分支版本 PERCONA 8.0.25 錯誤日誌裡面沒有詳細的資訊.不知道是真使用還是假使用.


        #後續查詢500條記錄 減少了3個大頁

        [root@localhost ~]# cat /proc/meminfo | grep Page

        AnonPages:        413920 kB

        PageTables:         5380 kB

        AnonHugePages:         0 kB

        HugePages_Total:    2290

        HugePages_Free:     2214

        HugePages_Rsvd:     2036

        HugePages_Surp:        0

        #從這裡發現 大頁記憶體的保留頁確實給INNODB BUF裝備的,並且使用之.



        #MYSQL 哪個部分不使用大頁記憶體的呢? 187MB

          mysql>  SELECT    ->  ROUND(@@key_buffer_size/1024/1024,2) as SHARE_KEY_BUF_MB,    ->  ROUND(@@innodb_buffer_pool_size/1024/1024,2) as SHARE_BUF_POOL ,    ->  ROUND(@@innodb_log_buffer_size/1024/1024,2) as LOG_BUF,    ->  ROUND(@@tmp_table_size/1024/1024,2) as PRV_TMP_TABLE,    ->  ROUND(@@read_buffer_size/1024/1024,2) as PRV_READ_BUF,    ->  ROUND(@@sort_buffer_size/1024/1024,2) as PRV_SORT_BUF,    ->  ROUND(@@join_buffer_size/1024/1024,2) as PRV_JOIN_BUF,    ->  ROUND(@@read_rnd_buffer_size/1024/1024,2) as PRV_READ_RND_BUF,    ->  ROUND(@@binlog_cache_size/1024/1024,2) as PRV_BINLOG_CACHE,    ->  ROUND(@@thread_stack/1024/1024,2) as THREAD_STACK,    ->  (SELECT COUNT(host) FROM information_schema.processlist ) as connects;+------------------+----------------+---------+---------------+--------------+--------------+--------------+------------------+------------------+--------------+----------+| SHARE_KEY_BUF_MB | SHARE_BUF_POOL | LOG_BUF | PRV_TMP_TABLE | PRV_READ_BUF | PRV_SORT_BUF | PRV_JOIN_BUF | PRV_READ_RND_BUF | PRV_BINLOG_CACHE | THREAD_STACK | connects |+------------------+----------------+---------+---------------+--------------+--------------+--------------+------------------+------------------+--------------+----------+|             8.00 |        4096.00 |   16.00 |         16.00 |         8.00 |         8.00 |         8.00 |             8.00 |            16.00 |         0.25 |        4 |+------------------+----------------+---------+---------------+--------------+--------------+--------------+------------------+------------------+--------------+----------+1 row in set (0.00 sec)


          #執行緒記憶體

          64.25*4=257MB  大約哦


          #mysql 5.73 查執行緒記憶體和共享記憶體

          
          select VARIABLE_NAME, VARIABLE_VALUE, 
          concat(VARIABLE_VALUE/
          1024/
          1024,
          ' MB'AS VARIABLE_VALUE_MB 
          
            from information_schema.SESSION_VARIABLES 
          where variable_name  in ( 'innodb_buffer_pool_size', 'innodb_log_buffer_size', 'innodb_additional_mem_pool_size', 'key_buffer_size', 'query_cache_size');

            select VARIABLE_NAME, VARIABLE_VALUE,  concat(VARIABLE_VALUE/ 1024/ 1024, ' MB'AS VARIABLE_VALUE_MB 
          from information_schema.SESSION_VARIABLES 
          where variable_name  in( 'read_buffer_size', 'read_rnd_buffer_size', 'sort_buffer_size', 'join_buffer_size', 'binlog_cache_size', 'tmp_table_size');



          #重複啟動測試


            
            [root@localhost ~]
            # free -m
            
            
            
                         total        used        free      shared  buff/cache   available
            Mem:           7821        4771        2216          23         833        2350
            Swap:          8063          25        8038
              
              [root@localhost ~]
              # cat /proc/meminfo | grep Page
              
              
              
              AnonPages:         53376 kB
              PageTables:         3972 kB
              AnonHugePages:         0 kB
              HugePages_Total:    2290
              HugePages_Free:     2290
              HugePages_Rsvd:        0
              HugePages_Surp:        0
              [root@localhost ~] # service mysqld start
              Redirecting to /bin/systemctl start mysqld.service


                
                [root@localhost ~]
                # free -m
                
                
                
                             total        used        free      shared  buff/cache   available
                Mem:           7821        5104        1883          23         832        2017
                Swap:          8063          25        8038

                [root@localhost ~] # cat /proc/meminfo | grep Page
                AnonPages:        393856 kB
                PageTables:         5276 kB
                AnonHugePages:         0 kB
                HugePages_Total:    2290
                HugePages_Free:     2217
                HugePages_Rsvd:     2039
                HugePages_Surp:        0


                5104-4771=333MB


                HTOP 1.2 顯示MYSQLD 佔用實體記憶體 RES項為 354MB 



                5119-4771=348

                2290-1718=572*2=1144MB


                #大查詢被超時被KILL 後

                [root@localhost ~]# free -m

                              total        used        free      shared  buff/cache   available

                Mem:           7821        5119        1869          23         833        2002

                Swap:          8063          25        8038


                [root@localhost ~]# cat /proc/meminfo | grep Page

                AnonPages:        405212 kB

                PageTables:         5412 kB

                AnonHugePages:         0 kB

                HugePages_Total:    2290

                HugePages_Free:     1718

                HugePages_Rsvd:     1540

                HugePages_Surp:        0


                5119-4771=348

                2290-1718=572*2=1144MB


                證明 MYSQL繼續使用大頁記憶體 用在INNODB BUF上


                #關閉大頁記憶體測試大表查詢 


                [root@localhost ~]# cat /proc/meminfo | grep Page

                AnonPages:         54240 kB

                PageTables:         4124 kB

                AnonHugePages:         0 kB

                HugePages_Total:    2290

                HugePages_Free:     2290

                HugePages_Rsvd:        0

                HugePages_Surp:        0




                [root@localhost ~]# cat /proc/meminfo | grep Page

                AnonPages:       1530156 kB

                PageTables:         7736 kB

                AnonHugePages:         0 kB

                HugePages_Total:    2290

                HugePages_Free:     2290

                HugePages_Rsvd:        0

                HugePages_Surp:        0


                #頁表增長 

                7736-4124=3612KB

                開大頁記憶體 

                5412-3972=1440KB


                OOM分數


                大頁

                [root@localhost etc]# sh look_mysql_oom.sh 

                Mysql Now OOM SCORE:

                25

                SCORE ADJ:

                0

                0

                ADJ OOM

                0

                25

                0


                傳統頁

                [root@localhost etc]# sh look_mysql_oom.sh 

                Mysql Now OOM SCORE:

                29

                SCORE ADJ:

                0

                0

                ADJ OOM

                0

                29

                0


                生產環境的傳統頁

                [fankun@_DC_CoreDB]sh  look_mysql_oom.sh

                Mysql Now OOM SCORE:

                210

                SCORE ADJ:

                0

                0

                ADJ OOM

                0

                210

                0

                [fankun@paylabs_DC_CoreDB]free -m

                              total        used        free      shared  buff/cache   available

                Mem:          11852        8241        1207          40        2403        3256

                Swap:         24571          32       24539


                OOM得分也有所降低


                最後總結 MYSQL 從5.7 就支援大頁記憶體,只支援共享記憶體單元,也就是全域性記憶體,執行緒記憶體不能使用大頁記憶體. MYSQL使用大頁記憶體是逐步使用的.不必ORACLE 有個PRE_SGA引數 先分配記憶體.ORACLE可以一下子就把大頁記憶體使用完.而不是 HugePages_Rsvd 保留多少.

                另外PS庫的記憶體不太好估算.

                另外CENTOS 7 TOP和HTOP RES顯示MYSQLD實際佔用實體記憶體, 這個應該是包含傳統頁和大頁兩部分.有些大佬說大頁記憶體不會被統計在程式使用中.

                或許CENTOS 7以前的作業系統沒辦法統計吧.


                最後我們還要估算出 最大執行緒X執行緒記憶體各項. 這些記憶體使用的4K頁的傳統記憶體. 傳統頁記憶體+大頁記憶體+系統自身佔用記憶體 不要超過90%或者80%報警線.避免運維瞎嗶嗶.


                很多人說 MYSQL一般不開大頁記憶體 

                是的 此話非常政治正確, 一般嘛!  一般 也是隻那個年代下 記憶體+CPU+使用者併發執行緒量.


                第一 MYSQL採用執行緒, 比ORACLE和PG採用程式 消耗系統頁表 非常小,不那麼明顯. 因為每個程式都要COPY一份共享記憶體,每份程式的共享記憶體都要佔用頁表,  而執行緒模型只有一份,執行緒之間是共享系統頁面.


                第二 顯然當 INNODB BUF 達到一定程度後 它佔用的系統頁表也非常大的.

                MYSQL 佔用了11812KB的系統頁表,對應記憶體 5884- 202 =5480 MB

                11812/5480=2.155KB/MB 每兆記憶體要消耗2.15KB頁表

                那麼140GB的INNODB BUF 呢?

                308,940.8KB =301MB 加上強勁的CPU還是不那麼影響效能.


                為此開大頁記憶體的MYSQL 還是一定程度有效率的提升, 沒有ORACLE和PG那麼立竿見影.



                來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/680758/viewspace-3007848/,如需轉載,請註明出處,否則將追究法律責任。

                相關文章