Linux 有很多很好的内存、IO调度机制,但是并不会适用于所有场景。对于运维人员来说,Linux比较让人头疼的一个地方是:它不会因为MySQL很重要就避免将分配给MySQL的地址空间映射到swap上。对于频繁进行读写操作的系统而言,数据看似在内存而实际上在磁盘是非常糟糕的,响应时间的增长很可能直接拖垮整个系统。所以,作为运维人员,怎样做到尽量避免 MySQL
惨遭 Swap 的毒手将显得尤为重要!
SWAP是操作系统虚拟出来的一部分内存地址,它的物理存储元件是磁盘。在备份数据或恢复数据时,文件系统会向Linux系统请求大量的内存作为cache。在物理内存使用殆尽时候,为了确保程序运行,往往会将另外的一些占用物理内存地址空间的程序映射到swap分区上。
操作系统设置swap的目的
程序运行的一个必要条件就是足够的内存,而内存往往是系统里面比较紧张的一种资源。为了满足更多程序的要求,操作系统虚拟了一部分内存地址,并将之映射到swap上。对于程序来说,它只知道操作系统给自己分配了内存地址,但并不清楚这些内存地址到底映射到物理内存还是swap。物理内存和swap在功能上是一样的,只是因为物理存储元件的不同(内存和磁盘),性能上有很大的差别。操作系统会根据程序使用内存的特点进行换入和换出,尽可能地把物理内存留给最需要它的程序。
但是这种调度是按照预先设定的某种规则的,并不能完全符合程序的需要。一些特殊的程序(比如MySQL)希望自己的数据永远寄存在物理内存里,以便提供更高的性能。于是操作系统就设置了几个api,以便为调用者提供"特殊服务"。
服务器产生Swap分区的原因
-
1)copy一个大文件,比如上百G的backup包
-
2)正在mysqldump以及mysql import一个很大的库的时候。
-
3)大批量的并发操作的io writer和io read操作。
MySQL程序运行时,物理内存为MySQL分配了大量的物理地址空间,以提高执行的速率。为了避免在执行消耗大量内存的操作时将MySQL所拥有的部分物理内存地址空间映射到swap分区上(比如出现了MySQL服务器Swap满了100%导致db很慢很卡的现象),可做一下调整(解决办法):
1)改系统内核参数/proc/sys/vm/swappiness
。调整系统使用swap分区的倾向性,数值越低越倾向于释放文件系统的cache,不能避免Linux系统使用swap分区。swappiness=0表示最大限度使用物理内存,然后才是swap分区。swappiness=100表示积极使用swap分区,并且将内存上的数据及时的映射到swap分区上。
/proc/sys/vm/swappiness 的内容改成0(临时),/etc/sysctl.conf上添加vm.swappiness=0(永久)这个参数,Linux是倾向于使用swap,还是倾向于释放文件系统cache。在内存紧张的情况下,数值越低越倾向于释放文件系统cache。当然,这个参数只能减少使用swap的概率,并不能避免Linux使用swap。
2)改MySQL参数innodb_flush_method
,开启O_DIRECT模式。Innodb的buffer pool会直接绕过文件系统cache来访问磁盘,但是redo log依旧会使用文件系统cache。Redo Log是覆写模式的,即使使用了文件系统的cache也不会占用太多
3)加MySQL配置参数memlock
。将MySQL锁定在内存中防止被swapping out。这个参数会强迫mysqld进程的地址空间一直被锁定在物理内存上,对于os来说是非常霸道的一个要求。必须要用root帐号来启动MySQL才能生效。
4)指定MySQL使用大页内存
(Large Page)。Linux上的大页内存是不会被换出物理内存的,和memlock有异曲同工之妙。
5)临时释放锁
占据的swap。
在Mysql数据库维护中,会遇到的一个现象:MySQL内存持续增加,最高时物理内存消耗达到90%以上,导致swap使用率100%,进而造成内存不足,系统自动kill mysql进程。Mysql服务挂掉,查看Mysql的error日志信息: [ERROR] InnoDB: Unable to lock /usr/local/mysql/var/ibdata1, error: 11
或者
-
InnoDB: mmap(137363456 bytes) failed; errno 12
-
2016-03-01 01:38:42 13064 [ERROR] InnoDB: Cannot allocate memory for the buffer pool
-
2016-03-01 01:38:42 13064 [ERROR] Plugin 'InnoDB' init function returned error.
-
2016-03-01 01:38:42 13064 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
-
2016-03-01 01:38:42 13064 [ERROR] Unknown/unsupported storage engine: InnoDB
-
2016-03-01 01:38:42 13064 [ERROR] Aborting
出现上面报错的原因一般是系统内存资源不足造成的(error 11在mysql中是资源临时不可用),解决方法是升级系统内存或者添加swap;