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=16MBinnodb_buffer_pool_size=4294967296binlog_cache_size=16777216innodb_log_buffer_size=16777216innodb_buffer_pool_dump_at_shutdown = OFFinnodb_buffer_pool_load_at_startup = OFFlarge-pages#locked_in_memory=YES#### Thread Memon Setjoin_buffer_size=8388608sort_buffer_size=8388608read_buffer_size=8388608read_rnd_buffer_size=8388608tmp_table_size=16777216#bulk_insert_buffer_size=8388608thread_cache_size = 32thread_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 -mtotal used free shared buff/cache availableMem: 7821 4771 2216 23 833 2350Swap: 8063 25 8038
[root@localhost ~]# cat proc/meminfo | grep PageAnonPages: 53376 kBPageTables: 3972 kBAnonHugePages: 0 kBHugePages_Total: 2290HugePages_Free: 2290HugePages_Rsvd: 0HugePages_Surp: 0[root@localhost ~]# service mysqld startRedirecting to bin/systemctl start mysqld.service
[root@localhost ~]# free -mtotal used free shared buff/cache availableMem: 7821 5104 1883 23 832 2017Swap: 8063 25 8038[root@localhost ~]# cat proc/meminfo | grep PageAnonPages: 393856 kBPageTables: 5276 kBAnonHugePages: 0 kBHugePages_Total: 2290HugePages_Free: 2217HugePages_Rsvd: 2039HugePages_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那么立竿见影.
安装
using filesort VS using temporary
备份和恢复
逻辑
物理
MYSQL xtrabackup 全量压缩备份
MYSQL 8 加密和流失备份
MYSQL xtrabackup 增量备份
MYSQL 8 物理全量恢复2
主从复制
运维优化
SQL优化
mysql大量的waiting for table level lock怎么办
MYSQL开发
MYSQL分区维护
MGR集群
dba+开源工具:MySQL 8.0 MGR高可用VIP切换脚本
源码阅读
压测试工具
MYSQL 安全




