云计算让我们在互联网上拥有自己的私有虚拟服务器非常实惠。Digital Ocean提供每月5美元的入门级Droplet,而亚马逊在EC2平台上拥有微型实例层,第一年是免费的。如果您想测试一些新技术(多源复制?)或将其概念放在一起,这些实例是非常有用的。然而,这些服务器具有非常低的内存,通常在半个GB到1GB之间。而现在,通常能看到生产级数据库服务器的内存是上述的100倍。 100MB的内存使用对这些打内存服务器来说不会有显著差异,但是对512MB的虚拟机绝对非常可观。我最近遇到了一个MySQL不能启动的问题。有趣的是MySQL缺乏任何错误提示:
140521 08:26:40 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
140521 08:26:41 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid
但是,如果我们检查我们的内核消息,我们清楚地看到内存不足的事件:
May 21 08:26:41 aes2 kernel: Out of memory: Kill process 24774 (mysqld) score 842 or sacrifice child
May 21 08:26:41 aes2 kernel: Killed process 24774, UID 0, (mysqld) total-vm:549180kB, anon-rss:437324kB, file-rss:44kB
或者在其他情况下,我们看到InnoDB无法分配缓冲池的错误:
2014-05-21 08:33:23 25042 [Note] InnoDB: Initializing buffer pool, size = 128.0M InnoDB: mmap(137363456 bytes) failed; errno 12
2014-05-21 08:33:23 25042 [ERROR] InnoDB: Cannot allocate memory for the buffer pool
但是我们确实有RAM可用:
[root@aes2 ~]# free -m total used free shared buffers cached Mem: 490 86 403 0 7 32 -/+ buffers/cache: 46 443 Swap: 0 0 0
[root@aes2 ~]#
那么这里的问题是性能机制,所以不是很明显。MySQL启动时,它会分配所需的所有RAM。默认情况下,它将使用大约400MB的RAM,这对于具有64GB RAM的数据库服务器基本可以无视,但是对于小型虚拟机来说这是非常要命的。如果您添加默认的InnoDB缓冲池设置为128MB,就会轻易地超过512MB RAM分配,这还不包括任何操作系统占用的内存。我们可以通过将下面的命令放在[mysqld]部分配置下面,轻松地禁用性能优化模式:
performance_schema = off
当然也可以在性能模式(Performance Schema)下自定义使用那些监视器来减少内存占用。虽然内存受限,最好也能使用所有的功能,比如缓存(buffer pool)。有一个MySQL错误报告提供了关于性能模式的一个非常好的描述:[http://bugs.mysql.com/bug.php?id=68514]http://bugs.mysql.com/bug.php?id=68514。还有一个功能请求来打印用于性能模式的内存量,这将使整个问题更加可见:[http://bugs.mysql.com/bug.php?id=69665]http://bugs.mysql.com/bug.php?id=69665