MYSQL 主库操作大表DDL ,从库崩溃与系统参数错误设置

2021-06-07 00:00:00 参数 系统 内存 分配 空闲


事情是这样的,一个用户测试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 可能会发生的问题.


相关的代码


  1. int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)

  2. {

  3.     unsigned long free, allowed;


  4.     vm_acct_memory(pages);


  5.     /*

  6.      * Sometimes we want to use more memory than we have

  7.      */

  8.     if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS) //overcommit_memory=1,直接返回成功,不做任何限制。

  9.         return 0;


  10.     if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { //overcommit_memory=0,启发式方式,根据当前系统中空闲内存状况来决定是否可以分配内存。

  11.         unsigned long n;


  12.         free = global_page_state(NR_FILE_PAGES);

  13.         free += nr_swap_pages;


  14.         /*

  15.          * Any slabs which are created with the

  16.          * SLAB_RECLAIM_ACCOUNT flag claim to have contents

  17.          * which are reclaimable, under pressure. The dentry

  18.          * cache and most inode caches should fall into this

  19.          */

  20.         free += global_page_state(NR_SLAB_RECLAIMABLE)


  21.         /*

  22.          * Leave the last 3% for root

  23.          */

  24.         if (!cap_sys_admin)

  25.             free -= free / 32; //root用户可以在free更少(3%)的时候,分配内存。


  26.         if (free > pages) // pages为需要分配的内存大小,free为根据一定规则算出来的“空闲内存大小”,次free仅为NR_FILE_PAGES+NR_SLAB_RECLAIMABLE,由于直接或者系统中“实际空闲”内存代价比较大,所以进行分阶判断,提高效率。

  27.             return 0;


  28.         /*

  29.          * nr_free_pages() is very expensive on large systems,

  30.          * only call if we're about to fail.

  31.          */

  32.         n = nr_free_pages(); //当次判断不满足内存分配条件时,再进行“实际空闲”内存的获取操作。


  33.         /*

  34.          * Leave reserved pages. The pages are not for anonymous pages.

  35.          */

  36.         if (n <= totalreserve_pages)

  37.             goto error;

  38.         else

  39.             n -= totalreserve_pages;


  40.         /*

  41.          * Leave the last 3% for root

  42.          */

  43.         if (!cap_sys_admin)

  44.             n -= n / 32;

  45.         free += n;


  46.         if (free > pages)

  47.             return 0;


  48.         goto error;

  49.     }


  50.     allowed = (totalram_pages - hugetlb_total_pages()) //当overcommit_memory=2时,根据系统中虚拟地址空间的总量来进行限制。

  51.          * sysctl_overcommit_ratio / 100;

  52.     /*

  53.      * Leave the last 3% for root

  54.      */

  55.     if (!cap_sys_admin)

  56.         allowed -= allowed / 32;

  57.     allowed += total_swap_pages;


  58.     /* Don't let a single process grow too big:

  59.      leave 3% of the size of this process for other processes */

  60.     if (mm)

  61.         allowed -= mm->total_vm / 32;


  62.     if (percpu_counter_read_positive(&vm_committed_as) < allowed)

  63.         return 0;

  64. error:

  65.     vm_unacct_memory(pages);


  66.     return -ENOMEM;

  67. }



相关文章