好久没写纯技术的文章了,今天就写一篇吧。今天这篇文章讨论的技术问题,不仅对于国产数据库,对于使用Oracle、MySQL、PG等数据库的用户,同样有帮助。
前几天遇到一个案例,某国产数据库因为服务器内存耗尽OOM-KILL把数据库实例杀了。分析原因是因为在被杀之前有大量的SORT和HASH JOIN,因为Linux服务器上关闭了SWAP,所以物理内存耗尽就把占用内存最大的数据库服务进程杀掉了。
我建议用户设置一个合理的SWAP,避免类似问题再发生。不过用户和数据库原厂交流后,说原厂不建议开启SWAP。确实,不少数据库原厂的工程师都告诫用户不要开启SWAP,从而避免因为内存交换而引发性能问题。
这方面的数据库原厂观点在ORACLE时代是没有的,因为Oracle安装手册里都会建议设置合理的SWAP。我也多次和数据库原厂的工程师争论过这个问题。他们的观点是,开了SWAP,哪怕物理内存够用,也会有部分SWAP被使用,甚至大量SWAP被使用。这样就会引发不必要的性能问题。
对SWAP存在种种误解,正是因为这些误解的存在,才会让大家对使用SWAP心存疑虑。今天我们对这些误解做一个分析。
第一个问题是,为什么在一些物理内存剩余量很大的系统中,还会有SWAP被使用,这种情况会引发系统的性能问题吗?
在一个内存足够的系统中,可能会有部分SWAP被使用。这是十分常见的事情 。当物理内存分配出现不足的时候,如果SWAP还有空间可用,就会使用SWAP。这种物理内存无法分配的情况十分复杂,可能是一个物理内存使用高峰出现过瞬间无法分配内存的情况,也可能是NUMA某个节点上无法分配内存,也有可能当时部分内存正在写盘,无法释放导致,还有可能是内存碎片化,无法分配大型的连续内存。不管什么原因,有一部分不活跃的内存就被写入SWAP了。
可能缺内存只是瞬间,很快系统就有大块的可用内存了。但是这部分已经SWAP的内存是不会立即从SWAP转储到物理内存中的。只有当这部分内存再次被使用,变成活跃的时候,才会从SWAP转储到内存中。SSD的访问延时是物理内存的1000倍,因此哪怕使用SSD盘,如果访问了SWAP中的数据,都会慢很多。如果某些内存被SWAP后,长时间没有被用到,那么这部分SWAP就一直存在了。这就是我们看到的现象。
这种情况的存在,大概率不会产生系统性能问题,长久不活跃的内存,很可能永远不会被用到了。
因此对于第一个问题 ,我们的结论是 ,只要SWAP不是活跃的,SWAP空间被大量占用,绝大多数情况下,是不会影响到数据库的性能的。确保物理内存有足够的空闲空间,就不怕SWAP带来的性能问题。
在现代内存十分充足的系统中,SWAP的作用是当物理内存出现偶发性不足的时候,确保关键进程不会因为OOM KILLER的作用 而被杀掉。
数据库服务器的物理内存使用峰值十分不确定,因此开启SWAP一般不会带来严重的性能问题,建议大家开启。
第二个问题是,SWAP需要设置多大才合适?
既然数据库服务器的SWAP是建议开启的 ,那么SWAP设置多大才合适呢?在二三十年前的UNIX系统上,内存十分稀缺,而硬盘相对便宜很多,因此当时都是建议SWAP不小于物理内存的。随着硬件的发展,这种情况也在变化,Oracle 11g一般建议swap不小于物理内存的1/3。基于现代硬件,我给出的建议一般是20%左右。
这是一个综合权衡的结果,因为现在的SWAP已经不是为了防止内存不足了,而是为了应对偶发性内存不足时确保关键业务不会KILL。使用了SWAP之后也会遇到一些极端的问题,那就是说当 SWAP开始的时候,系统性能就开始下降了。如果我们没有发现,没有干预,系统的业务高峰也继续在持续,那么SWAP还会一直持续活跃,当SWAP被占满之前,这段时间系统性能一直处于下降阶段。直到SWAP耗尽,OOM-KILLER被启用。倒霉蛋被 杀掉,系统自动恢复正常。如果我们对数据库核心进程设置了OOM SCORE参数,那么数据库核心进程不会被杀,OOM KILLER激活后,系统 反而恢复性能了。这个现象 ,也是建议SWAP不要设置过大的一个原因。
第三个问题,在 启用SWAP的数据库系统中,操作系统还有一些什么样的配置建议?
在启用SWAP的数据库系统中,swappiness建议设置小一些,低于10,甚至直接设置为0,这样SWAP的使用倾向会小一些。同时支持大页的数据库能启用大页 ,最好还是启用大页,这样共享内存会使用大页,这些大页不会被SWAP,可以确保数据库性能。另外数据库核心进程的oom score可以设置一下,确保OOM-KILLER不会杀掉数据库的核心进程。
最后一个问题,如果我看着长期不释放的SWAP不爽,有什么办法清空它?
长时间存在的swap虽然大多数情况下无害,不过偶发性还是有可能会引发性能毛刺的。比如说某些内存是某个系统调度的进程使用的 ,十天半个月突然活跃了一下,而这个系统进程在工作时会引发一些全局锁,而正好抽风在一个交易系统的关键时刻启动了,那时候就会产生一个系统运行毛刺。因此对于某些系统,定期清理swap也是应该的。
想要清理掉swap,在确保物理内存足够用,并且系统没有关键业务在执行的时候,只需要swapoff -a就可以关闭swap了,此时所有的swap都会转储到内存。然后再swapon -a就可以重新开启swap了。