MYSQL 主库操作大表DDL ,从库崩溃与系统参数错误设置
事情是这样的,一个用户测试UAT库,从库无故的频繁的报错
而内存本身是OK的。但为什么是这样的 MYSQL 的版本是官版的8.011
首先我这边在拿到这个问题,想通过PERCONA 的工具集中的pt-pmp 来进行分析,但是在启动pt-pmp 后发现无法运行,直接报 virtual memory exhausted
但问题是内存没有用完,我们也有SWAP呀, 到底就怎么就无法分片内存了。这里突然想起之前看到过的一篇文章,是不是因为 overcommit_memory的配置有问题,导致这个明明有内存,但就是无法分配的问题。
首先我们再熟悉一下overcommit 的值为0 1 2
默认大部分系统选择为 0 , 官方文档的描述为适用于典型的系统,对严重超出预期的内存的分配会拒绝,并且会尽量少的使用SWAP 的内存空间
1 则是一个特别的列子,他并不关心系统的内存是否已经超分了,这样的配置仅仅适用于一些特别的应用程序。
2 则是和 1 的反例,他提供的内存分配仅仅会对整体的系统的50%进行分配, SWAP + 整体的内存的 50% 是他多能分配的,当无法对应用程序分配内存,系统并不会OOM应用,但应用会接受到一个内存分配的错误。
下面我个反应是查询 /proc/sys/vm/overcommit_memory ,果然里面的状态是 2 .
马上修改参数 sudo vi /etc/sysctl.conf
然后在执行 sysctl -p
再次启动PT-PMP 命令
pt-pmp --binary mysqld --iterations 2 --interval 1 --save-samples mysql.txt
在修改后
在查看MYSQL 的错误日志,,从修改后,系统目前也就没有错误了. 后来其他的DBA 想起来当初是为了测试这个参数对数据库的影响,而调整了参数. 忘记改回来了.不过也好,通过这个事情也彻彻底底的弄清楚 overcommit 参数如果在默认情况下设置成 2 ,MYSQL 可能会发生的问题.
相关的代码
int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
{
unsigned long free, allowed;
vm_acct_memory(pages);
/*
* Sometimes we want to use more memory than we have
*/
if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS) //overcommit_memory=1,直接返回成功,不做任何限制。
return 0;
if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { //overcommit_memory=0,启发式方式,根据当前系统中空闲内存状况来决定是否可以分配内存。
unsigned long n;
free = global_page_state(NR_FILE_PAGES);
free += nr_swap_pages;
/*
* Any slabs which are created with the
* SLAB_RECLAIM_ACCOUNT flag claim to have contents
* which are reclaimable, under pressure. The dentry
* cache and most inode caches should fall into this
*/
free += global_page_state(NR_SLAB_RECLAIMABLE);
/*
* Leave the last 3% for root
*/
if (!cap_sys_admin)
free -= free / 32; //root用户可以在free更少(3%)的时候,分配内存。
if (free > pages) // pages为需要分配的内存大小,free为根据一定规则算出来的“空闲内存大小”,次free仅为NR_FILE_PAGES+NR_SLAB_RECLAIMABLE,由于直接或者系统中“实际空闲”内存代价比较大,所以进行分阶判断,提高效率。
return 0;
/*
* nr_free_pages() is very expensive on large systems,
* only call if we're about to fail.
*/
n = nr_free_pages(); //当次判断不满足内存分配条件时,再进行“实际空闲”内存的获取操作。
/*
* Leave reserved pages. The pages are not for anonymous pages.
*/
if (n <= totalreserve_pages)
goto error;
else
n -= totalreserve_pages;
/*
* Leave the last 3% for root
*/
if (!cap_sys_admin)
n -= n / 32;
free += n;
if (free > pages)
return 0;
goto error;
}
allowed = (totalram_pages - hugetlb_total_pages()) //当overcommit_memory=2时,根据系统中虚拟地址空间的总量来进行限制。
* sysctl_overcommit_ratio / 100;
/*
* Leave the last 3% for root
*/
if (!cap_sys_admin)
allowed -= allowed / 32;
allowed += total_swap_pages;
/* Don't let a single process grow too big:
leave 3% of the size of this process for other processes */
if (mm)
allowed -= mm->total_vm / 32;
if (percpu_counter_read_positive(&vm_committed_as) < allowed)
return 0;
error:
vm_unacct_memory(pages);
return -ENOMEM;
}
相关文章