freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

高性能MySQL:内存交换区
2021-11-18 10:13:26


      当操作系统因为没有足够的内存而将一 些虚拟内存写到磁盘就会发生内存交换。内存交换对操作系统中运行的进程是透明的。只有操作系统知道特定的虚拟内存地址是在物理内存还是硬盘。

      内存交换对MySQL性能影响是很精糕的。它破坏了缓存在内存的目的,并且相对于使用很小的内存做缓存,使用交换区的性能更差。MySOL和存储引单有很多算法来区别对待内存中的数据和硬盘上的数据,因为般都假设内存数据访向代价更低。

      因为内存交换对用户进程不可见,MySQL (成存储引擎)并不知道数据实际上已经移动到磁盘,还会以为在内存中。

      结果会导致很差的性能。例如,若存储引擎认为数据依然在内存,可能觉得为“短析”的内存操作锁定一个全局互斥变量(例如InoDB缓冲池Mutex)是OK的。如果这个操作实际上引起了硬盘I/O,直到I/0操作完成前任何操作都会被挂起。这意味着内存交换比直接做硬盘I/O操作还要糟糕。

高性能MySQL:内存交换区

      在GNU/Linux上,可以用vmstat (在下一部分展示了一些例子)来监控内存交换。最好查看si和so列报告的内存交换1I/O活动,这比看swpd列报告的交换区利用率更重要。swpd列可以展示那些被载入了但是没有被使用的进程,它们并不是真的会成为问题。我们喜欢si和so列的值为0,并且一定要保证它们低于每秒10个块。

      极端的场景下,太多的内存交换可能导致操作系统交换空间溢出。如果发生了这种情况,缺乏虚拟内存可能让MySQL崩溃。但是即使交换空间没有溢出,非常活跃的内存交换也会导致整个操作系统变得无法响应,到这种时候甚至不能登录系统去杀掉MySQL进程。有时当交换空间溢出时,甚至Linux内核都会完全hang住。

      绝不要让系统的虚拟内存溢出!对交换空间利用率做好监控和报警。如果不知道需要多少交换空间,就在硬盘上尽可能多地分配空间,这不会对性能造成冲击,只是消耗了硬盘空间。有些大的组织清楚地知道内存消耗将有多大,并且内存交换被非常严格地控制,但是对于只有少量多用途的MySQL实例,并且工作负载也多种多样的环境,通常不切实际。如果后者的描述更符合实际情况,确认给服务器一些 “呼吸” 的空间,分配足够的交换空间。

      在特别大的内存压力下经常发生的另一件事是内存不足(OOM), 这会导致踢掉和杀掉一些进程。在MySQL进程这很常见。在另外的进程上也挺常见,比如SSH,甚至会让系统不能从网络访问。可以通过设置SSH进程的oom adj 或oom score adj 值来避免这种情况。

      可以通过正确地配置MySQL缓冲来解决大部分内存交换问题,但是有时操作系统的虚拟内存系统还是会决定交换MySQL的内存。这通常发生在操作系统看到MySQL发出了大量I/O,因此尝试增加文件缓在来保在更多数据时,如果没有足够的内存,有些东西就必须被交换出去,有些可能就是MySQL本身。有些老的Linux内核版本也有些适得其反的优先级,导致本不应该被交换的被交换出去,但是在最近的内核都被缓解了。

      有些人主张完全禁用交换文件。尽管这样做有时在某些内核拒绝工作的极端场景下是可行的,但这降低了操作系统的性能(在理论上不会,但是实际上会的)。同时这样做也是很危险的,因为禁用内存交换就相当于给虚拟内存设置了一个不可动摇的限制。如果MySQL需要临时使用很大一块内存, 或者有很耗内存的进程运行在同一台机器(如夜间批量任务),MySQL 可能会内存溢出、崩溃,或者被操作系统杀死。

      操作系统通常允许对虚拟内存和I/O进行一些控制。我们提供过一些GNU/Linux上控制它们的办法。最基本的方法是修改/proc/sys/vm/swappiness为一个 很小的值,例如0或1.这告诉内核除非虚拟内存完全满了,否则不要使用交换区。下面是如何检查这个值的例子:

$ cat /proc/sys/vm/swappiness

这个值显示为60,这是默认的设置(范围是0~ 100)。对服务器而言这是个很糟糕的默认值。这个值只对笔记本适用。服务器应该设置为0 :

$ echo 0 > /proc/sys/vm/swappiness

      另一个选项是修改存储引擎怎么读取和写人数据。例如,使用innodb_flush method=0_DIRECT,减轻I/O压力。Direct I/O并不缓存,因此操作系统并不能把MySQL视为增加文件缓存的原因。这个参数只对InnoDB有效。你也可以使用大页,不参与换入换出。这对MyISAM和InnoDB都有效。

      另一个选择是使 用MySQL的memlock配置项,可以把MySQL锁定在内存。这可以避免交换,但是也可能带来危险:如果没有足够的可锁定内存,MySQL在尝试分配更多内存时会崩溃。这也可能导致锁定的内存太多而没有足够的内存留给操作系统。

      很多技巧都是对于特定内核版本的,因此要小心,尤其是当升级的时候。在某些工作负载下,很难让操作系统的行为合情合理,井且仅有的资源可能让缓冲大小达不到最满意的值。

# 系统安全 # 数据安全 # 网络安全技术
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者