ITPub博客

首页 > 数据库 > MySQL > 探索MYSQL开启大页内存

探索MYSQL开启大页内存

原创 MySQL 作者:zengmuansha 时间:2024-03-01 15:01:51 0 删除 编辑

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/ ,如需转载,请注明出处,否则将追究法律责任。

                请登录后发表评论 登录
                全部评论
                海鲨星际有限公司 超级 数据库架构师

                注册时间:2012-08-01

                • 博文量
                  14
                • 访问量
                  14348