探索MYSQL开启大页内存

来源:这里教程网 时间:2026-03-01 17:39:44 作者:

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那么立竿见影.

相关推荐