4.1 物理硬件限制
对性能有不切实际的期望是通常会犯的错。我们要求MySQL服务器在忽略硬件组件延迟的情况下进行优化。因此,理解什么导致了延迟很重要。
下面列出了影响MySQL服务器的硬件资源:
内存
CPU
内核数量
磁盘I/O
网络带宽
我们依次讨论每个细节。
4.1.1 内存
内存对于MySQL是非常宝贵的资源。服务器在没有磁盘交换的情况下运行很快。理想情况是数据驻留在内存中。因此,在物理内存的限制内合理配置缓冲区是非常重要的。关于这一点,1.6.4小节和3.9.3小节提供了更多详细的介绍和指导。
提示 提示
在Linux/UNIX上可以通过vmstat,或者Windows上的任务管理器来查看mysqld是否有大量磁盘交换。
这里列出Linux上一个磁盘交换的例子。重要的部分加粗显示。对于没有磁盘交换的服务器,这些值应该为0:
相关章节讨论了影响内存使用的配置变量。首先计算出MySQL服务器需要用到的最大内存量,基本原则是要保证它小于你的物理内存。当缓冲区大于实际内存时会增加MySQL服务器因为“内存不足”错误而崩溃的风险。
前面的观点可以换一种陈述方式:如果你需要更大的缓冲区,则需要购买更多内存。扩展应用程序时这始终是一个很好的做法。
使用的内存模块支持扩展错误校正(EEC),这样即使内存有一些损坏,MySQL服务器也不会因此崩溃。
关于内存使用的更多内容,可以参考MySQL参考手册中的“MySQL如何使用内存”章节。我就不在此处重复,因为它不涉及任何新排错技巧。
很重要的一点是,当查询的行包含BLOB字段时,内部缓冲区会增长到能存储该值的点,并且存储引擎在查询结束后不会释放内存。需要执行FLUSH TABLE来释放内存。
另一个要点涉及32位和64位架构的不同。虽然32位使用较小的指针大小可以节约内存,但由于操作系统的寻址受限,它在缓冲区大小设置上存在固有的约束。理论上,每个进程在32位系统上的最大可用内存为4GB,实际上在很多系统上这个数值很小。所以如果你想使用的缓冲区在32位系统上超过了这个值,考虑转换到64位架构下。
4.1.2 处理器与内核
MySQL的性能不会随着CPU的速度线性增长。这并不意味着你不能使用一块快的CPU,但不要期望提高CPU速度能像增加内存那样性能会有大幅提升。
然而,当设置一些影响内部线程并发的选项时,内核的数量很重要。如果你没有足够的内核数增加这些值是没有任何意义的。通过使用一款名叫sysbench[1]的基准工具能够轻松说明问题。表4-1显示了在四核机器上的一个测试结果。我使用具有16个线程的OLTP sysbench测试。
表4-1 不同innodb_thread_concurrency值下执行事件消耗的时间(s)
如你所见,在启动8个线程之前测试越运行越快,但随着数值的增加停止了增长。
4.1.3 磁盘I/O
快速磁盘对MySQL性能很重要。磁盘越快,I/O性能越好。
关于磁盘,你需要关注磁盘读延迟(每次读访问需要多长时间)和fsync延迟(每个fsync耗时多少)。
近来固态硬盘(SSD)的性能很好,但不要指望在上面出现奇迹,因为大多数存储引擎是针对硬盘读写优化的。
同样网络存储也是。可以将数据和日志文件放在网络文件系统或者存储上,但这些装置可能会慢于本地磁盘。你需要检查存储是否快速并且可靠,否则,如果由于网络故障引起数据丢失请不要感到意外。
在Linux/UNIX上使用iostat来判断磁盘I/O是否过载。向设备发起的请求平均队列长度正常情况下不会很高。出于同样的目的,你可以在Windows平台上使用perfmon。下面给出iostat的一个输出例子:
以上输出取自mysqld空闲并随后启动一个活跃的I/O作业时。你可以看到avgqu-sz是如何增长的。虽然还不至于带来问题,但我决定在这里通过这个例子来说明当mysqld正在处理它的作业时磁盘I/O活动是如何发生变化的。
除了速度之外,要牢记的是,存储也可能会丢失数据,可能出现只写入一部分页的情况。如果使用InnoDB,为了数据安全通过设置innodb_double_write使用双写缓冲区。同样,为磁盘准备备用电池是很重要的,它可能防止因为电源故障导致的数据丢失。
4.1.4 网络带宽
客户端几乎总是通过网络连接MySQL到服务器的,所以MySQL服务器运行在一个快速的网络环境下是很重要的。
除了网络带宽之外,往返时间(RTT)和往返次数也很重要。RTT指的是客户端发送网络包到服务端返回应答所消耗的时间。主机间隔的距离越长,RTT越高。
也正是因为存在网络带宽和RTT这些原因,如果可以,推荐将客户端和服务器放在同一个本地网络中。
复制也推荐在本地网络中进行。连接到从服务器时可以使用因特网来替代本地内联网,但预期会出现延迟,甚至中继日志数据损坏带来的报错。上面的错误应该在bug #26489 bug修复之后会自动修复,前提是你在5.5版本中配置了relay-log-recovery选项,或者从5.6版本开始使用二进制日志校验和。但由于网络故障主从服务器之间仍然会在重发包上消耗时间。
4.1.5 延迟效应的例子
为了结束本章内容,我用一个小例子来说明硬件延迟是如何影响一条普通的UPDATE查询的。我们使用InnoDB表并将自动提交打开,同时打开二进制日志文件。
这个简单的查询会在下面的情况下遭遇延迟:
客户端发送命令到服务端历经半个RTT。
执行UPDATE的WHERE子句,mysqld读磁盘。
由于自动提交开启mysqld会对此事务做一个fsync调用。
为写入二进制日志文件Mysqld做一次fsync调用。
为提交改变mysqld做一次fsync调用。
客户端收到来自服务器的结果,这是RTT的另一半。