暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

探索MYSQL开启大页内存

364

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


      SELECT
      ROUND(@@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=5480MB

                11812/5480=2.155KB/MB 每兆内存要消耗2.15KB页表

                那么140GB的INNODB BUF 呢?

                308,940.8KB =301MB 加上强劲的CPU还是不那么影响性能.


                为此开大页内存的MYSQL 还是一定程度有效率的提升, 没有ORACLE和PG那么立竿见影.




                安装

                MYSQL二进安装

                MYSQL8.0 二进制安装

                MYSQL8024二进制安装脚本

                Percona8.0 通用二进安装


                原理

                MySQL Truncate undo  表空间

                MYSQL两段提交BINGLOG REDOLOG关系

                MYSQL双写和块裂

                MySQL 可以添加多少 text字段?

                MYSQL 热数据备份--Warmup特性

                MySQL 线程池

                MySQL InnoDB 事务锁源码分析

                MYSQL SHUTDOWN 过程认识

                InnoDB buffer pool flush策略

                MySQL表定义缓存

                MYSQL 和 NUMA情爱

                MySQL Change buffer

                using filesort VS using temporary

                MYSQL REDO   内参

                MYSQL UNDO内参

                MYSQL InnoDB 预读

                MYSQL SYS CPU高的可能性分析

                MYSQL SHUTDOWN 过程认识

                MYSQL索引树理解

                InnoDB 的事务子系统

                InnoDB 崩溃恢复过程

                Adaptive hash index

                MYSQL DB_CACHE 基础

                MYSQL8.0索引算法问题


                备份和恢复

                逻辑

                MYSQL备份

                MYSQL的恢复

                使用MYSQLBINLOG工具恢复数据GTID范围

                手工闪回BINLOG的DELETE语句


                物理

                Mysql 物理备份Xtrabackup

                MYSQL xtrabackup 全量压缩备份
                MYSQL 8 加密和流失备份

                MYSQL xtrabackup 增量备份
                MYSQL 8 物理全量恢复2

                MYSQL 增量恢复


                主从复制

                重建MYSQL主从库

                MYSQL 最大可用模式

                MYSQL ACTIVE DG 配置

                MYSQL BINLOG 二进制日志

                mysql反向同步

                MYSQL从库的并发恢复

                MYSQL延迟并发复制

                MYSQL的只读GTID复制

                MYSQL从库应用缓慢

                Percona8.0 主从

                MYSQL主从重要参数原理

                MYSQL 主从复制数据不一致的风险



                运维优化

                理解MYSQL组提交和二阶段提交

                MySQL两地三中心方案初步设计

                MYSQL微服务架构

                MYSQL-PTONLINE 改分区表

                MYSQL经典PID问题

                MYSQL SQL巡检脚本

                用SHELL输出HTML的MYSQL巡检


                SQL优化

                MYSQL5.7优化了WHERE条件前后顺序

                基于案例理解MySQL执行计划

                MYSQL 单表千万变慢

                MYSQL也有HINT

                500万的单表性能

                MYSQL排序ORDER BY

                mysql大量的waiting for table level lock怎么办

                MYSQL METALOCK

                MYSQL 死锁

                MySQL的性能相关的视图

                MYSQL MEMCACHE插件

                MYSQL优化思路

                MYSQL LEFT JOIN 优化

                MYSQL 加字段优化

                MYSQL 字符集优化

                MYSQL ID 的混乱星海

                MYSQL优化TEMP



                MYSQL开发

                MYSQL 常用函数

                MYSQL 批量生成触发器

                如何优雅更新MYSQL大表?

                MySQL的LeftJoin



                MYSQL分区维护

                分区表

                Mysql5.7范围分区操作

                MYSQL普通表 在线 改成 分区表

                MYSQL为什么分区要加入主键和唯一索引?

                MYSQL在线分区之表锁


                MGR集群

                MYSQL MGR 集群

                MYSQL MGR 从入门到精通01

                MYSQL MGR 从入门到精通 02

                MYSQL MGR  从入门到精通03

                MGR重启

                dba+开源工具:MySQL 8.0 MGR高可用VIP切换脚本



                源码阅读

                MYSQL 源码DEBUG编译

                Mysql 2038 的BUG

                MYSQL DEBUG 版本的发布




                压测试工具

                SYSBENCH


                MYSQL 安全

                MYSQL-SSL配置

                MYSQL VAULT实践指南 一

                MYSQL VAULT实践指南 二

                MYSQL VAULT实践指南 三

                MYSQL VAULT实践指南 四

                MYSQL VAULT实践指南 五




                文章转载自海鲨数据库架构师,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                评论