网站后台内容管理,devmyapp,如何防范恶意网站,设计必知的设计网站 039文章目录 2.1 为什么需要基准测试2.2 基准测试的策略2.2.1 测试何种指标 2.3 基准测试方法2.3.1 设计和规划基准测试2.3.2 基准测试应该运行多长时间2.3.3 获取系统性能和状态2.3.4 获得准确的测试结果2.3.5 运行基准测试并分析结果2.3.6 绘图的重要性 2.4 基准测试工具… 文章目录 2.1 为什么需要基准测试2.2 基准测试的策略2.2.1 测试何种指标 2.3 基准测试方法2.3.1 设计和规划基准测试2.3.2 基准测试应该运行多长时间2.3.3 获取系统性能和状态2.3.4 获得准确的测试结果2.3.5 运行基准测试并分析结果2.3.6 绘图的重要性 2.4 基准测试工具2.4.2 单组件式测试工具 2.5 基准测试案例2.5.1 http_load2.5.2 MySQL基准测试套件2.5.3 sysbenchsysbench 的CPU基准测试sysbench 的文件 I/O 基准测试sysbench 的 OLTP 基准测试sysbench 的其他特性 2.5.4 数据库测试套件中的 dbt2 TPC-C 测试2.5.5 Percona的TPCC-MySQL测试工具 2.6 总结 基准测试benchmark 是 MySQL 新手和专家都需要掌握的一项基本技能。简单地说基准测试是针对系统设计的一种压力测试。通常的目标是为了掌握系统的行为。但也有其他原因如重现某个系统状态或者是做新硬件的可靠性测试。本章将讨论 MySQL 和基于 MySQL 的应用的基准测试的重要性、策略和工具。我们将特别讨论一下 sysbench 这是一款非常优秀的 MySQL 基准测试工具。 什么是基准测试 基准测试是一种测量和评估软件性能指标的活动例如对数据访问的带宽和延迟、对计算机的 CPU 进行浮点运算能够使用户清楚的了解每款 CPU 的运算能力、作业吞吐能力是不是可以满足应用程序的要求从这两个例子能够看出测试的结果是可以量化表现的按照测试过程实现的结果是相同或处于可接受的区间内的、测试对象的测试结果是具有线性关系的满足以上三点的就是基准测试。 2.1 为什么需要基准测试
为什么基准测试很重要因为基准测试是唯一方便有效的、可以学习系统在给定的工作负载下会发生什么的方法。基准测试可以观察系统在不同压力下的行为评估系统的容量掌握哪些是重要的变化或者观察系统如何处理不同的数据。基准测试可以在系统实际负载之外创造一些虚构场景进行测试。基准测试可以完成以下工作或者更多
验证基于系统的一些假设确认这些假设是否符合实际情况。重现系统中的某些异常行为以解决这些异常。测试系统当前的运行情况。如果不清楚系统当前的性能就无法确认某些优化的效果如何。也可以利用历史的基准测试结果来分析诊断一些无法预测的问题。模拟比当前系统更高的负载以找出系统随着压力增加而可能遇到的扩展性瓶颈。 规划未来的业务增长。基准测试可以评估在项目未来的负载下需要什么样的硬件需要多大容量的网络以及其他相关资源。这有助于降低系统升级和重大变更的风险。测试应用适应可变环境的能力。例如通过基准测试可以发现系统在随机的并发峰值下的性能表现或者是不同配置的服务器之间的性能表现。基准测试也可以测试系统对不同数据分布的处理能力。测试不同的硬件、软件和操作系统配置。比如 RAID 5还是 RAID 10更适合当前的系统如果系统从 ATA 硬盘升级到 SAN 存储对于随机写性能有什么帮助Linux 2.4 系列的内核会比 2.6 系列的可扩展性更好吗升级 MySQL 的版本能改善性能吗为当前的数据采用不同的存储引擎会有什么效果所有这类问题都可以通过专门的基准测试来获得答案。证明新采购的设备是否配置正确。笔者曾经无数次地通过基准测试来对新系统进行压测发现了很多错误的配置以及硬件组件的失效等问题。因此在新系统正式上线到生产环境之前进行基准测试是一个好习惯永远不要相信主机提供商或者硬件供应商的所谓系统已经安装好并且能运行多快的说法。如果可能执行实际的基准测试永远是一个好主意。
基准测试还可以用于其他目的比如为应用创建单元测试套件。但本章我们只关注与性能有关的基准测试。
基准测试的一个主要问题在于其不是真实压力的测试。基准测试施加给系统的压力相对真实压力来说通常比较简单。真实压力是不可预期而且变化多端的有时候情况会过于复杂而难以解释。所以使用真实压力测试可能难以从结果中分析出确切的结论。
基准测试的压力和真实压力在哪些方面不同有很多因素会影响基准测试比如数据量、数据和查询的分布但最重要的一点还是基准测试通常要求尽可能快地执行完成所以经常给系统造成过大的压力。在很多案例中我们都会调整给测试工具的最大压力以在系统可以容忍的压力阈值内尽可能快地执行测试这对于确定系统的最大容量非常有帮助。然而大部分压力测试工具不支持对压力进行复杂的控制。务必要记住测试工具自身的局限也会影响到结果的有效性。
使用基准测试进行容量规划也要掌握技巧不能只根据测试结果做简单的推断。例如假设想知道使用新数据库服务器后系统能够支撑多大的业务增长。首先对原系统进行基准测试然后对新系统做测试结果发现新系统可以支持原系统 40 倍的 TPS每秒事务数这时候就不能简单地推断说新系统一定可以支持 40 倍的业务增长。这是因为在业务增长的同时系统的流量、用户、数据以及不同数据之间的交互都在增长它们不可能都有 40 倍的支撑能力尤其是相互之间的关系。而且当业务增长到 40 倍时应用本身的设计也可能已经随之改变。可能有更多的新特性会上线其中某些特性可能对数据库造成的压力远大于原有功能。而这些压力、数据、关系和特性的变化都很难模拟所以它们对系统的影响也很难评估。
结论就是我们只能进行大概的测试来确定系统大致的余量有多少。当然也可以做一些真实压力测试和基准测试有区别但在构造数据集和压力的时候要特别小心而且这样就不再是基准测试了。基准测试要尽量简单直接结果之间容易相互比较成本低且易于执行。尽管有诸多限制基准测试还是非常有用的只要搞清楚测试的原理并且了解如何分析结果所代表的意义。
2.2 基准测试的策略
基准测试有两种主要的策略一是针对整个系统的整体测试另外是单独测试MySQL。这两种策略也被称为集成式full-stack以及单组件式single-component基准测试。针对整个系统做集成式测试而不是单独测试MySQL的原因主要有以下几点
测试整个应用系统包括Web服务器、应用代码、网络和数据库是非常有用的因为用户关注的并不仅仅是MySQL本身的性能而是应用整体的性能。MySQL并非总是应用的瓶颈通过整体的测试可以揭示这一点。只有对应用做整体测试才能发现各部分之间的缓存带来的影响。整体应用的集成式测试更能揭示应用的真实表现而单独组件的测试很难做到这一点。
另外一方面应用的整体基准测试很难建立甚至很难正确设置。如果基准测试的设计有问题那么结果就无法反映真实的情况从而基于此做的决策也就可能是错误的。
不过有时候不需要了解整个应用的情况而只需要关注 MySQL 的性能至少在项目初期可以这样做。基于以下情况可以选择只测试 MySQL
需要比较不同的 schema 或查询的性能。针对应用中某个具体问题的测试。为了避免漫长的基准测试可以通过一个短期的基准测试做快速的“周期循环”来检测出某些调整后的效果。
另外如果能够在真实的数据集上执行重复的查询那么针对 MySQL 的基准测试也是有用的但是数据本身和数据集的大小都应该是真实的。如果可能可以采用生产环境的数据快照。
不幸的是设置一个基于真实数据的基准测试复杂而且耗时。如果能得到一份生产数据集的拷贝当然很幸运但这通常不太可能。比如要测试的是一个刚开发的新应用它只有很少的用户和数据。如果想测试该应用在规模扩张到很大以后的性能表现就只能通过模拟大量的数据和压力来进行。
2.2.1 测试何种指标
在开始执行甚至是在设计基准测试之前需要先明确测试的目标。测试目标决定了选择什么样的测试工具和技术以获得精确而有意义的测试结果。可以将测试目标细化为一系列的问题比如“这种 CPU 是否比另外一种要快”或“新索引是否比当前索引性能更好”
有时候需要用不同的方法测试不同的指标。比如针对延迟latency和吞吐量throughput就需要采用不同的测试方法。
请考虑以下指标看看如何满足测试的需求。 吞吐量 吞吐量指的是单位时间内的事务处理数。这一直是经典的数据库应用测试指标。一些标准的基准测试被广泛地引用如 TPC-C参考 http://www.tpc.org 而且很多数据库厂商都努力争取在这些测试中取得好成绩。这类基准测试主要针对在线事务处理OLTP的吞吐量非常适用于多用户的交互式应用。常用的测试单位是每秒事务数TPS有些也采用每分钟事务数TPM。 响应时间或者延迟 这个指标用于测试任务所需的整体时间。根据具体的应用测试的时间单位可能是微秒、毫秒、秒或者分钟。根据不同的时间单位可以计算出平均响应时间、最小响应时间、最大响应时间和所占百分比。最大响应时间通常意义不大因为测试时间越长最大响应时间也可能越大。而且其结果通常不可重复每次测试都可能得到不同的最大响应时间。因此通常可以使用百分比响应时间percentile response time来替代最大响应时间。例如如果95的响应时间都是5毫秒则表示任务在 95 的时间段内都可以在 5 毫秒之内完成。 使用图表有助于理解测试结果。可以将测试结果绘制成折线图比如平均值折线或者95百分比折线或者散点图直观地表现数据结果集的分布情况。通过这些图可以发现长时间测试的趋势。本章后面将更详细地讨论这一点。 并发性 并发性是一个非常重要又经常被误解和误用的指标。例如它经常被表示成多少用户在同一时间浏览一个 Web 站点经常使用的指标是有多少个会话。然而HTTP 协议是无状态的大多数用户只是简单地读取浏览器上显示的信息这并不等同于 Web 服务器的并发性。而且Web 服务器的并发性也不等同于数据库的并发性而仅仅只表示会话存储机制可以处理多少数据的能力。Web服务器的并发性更准确的度量指标应该是在任意时间有多少同时发生的并发请求。 在应用的不同环节都可以测量相应的并发性。Web 服务器的高并发一般也会导致数据库的高并发但服务器采用的语言和工具集对此都会有影响。注意不要将创建数据库连接和并发性搞混淆。一个设计良好的应用同时可以打开成百上千个 MySQL 数据库服务器连接但可能同时只有少数连接在执行查询。所以说一个 Web 站点“同时有 50000 个用户”访问却可能只有 1015 个并发请求到 MySQL 数据库。 换句话说并发性基准测试需要关注的是正在工作中的并发操作或者是同时工作中的线程数或者连接数。当并发性增加时需要测量吞吐量是否下降响应时间是否变长如果是这样应用可能就无法处理峰值压力。 并发性的测量完全不同于响应时间和吞吐量。它不像是一个结果而更像是设置基准测试的一种属性。并发性测试通常不是为了测试应用能达到的并发度而是为了测试应用在不同并发下的性能。当然数据库的并发性还是需要测量的。可以通过 sysbench 指定 32、64 或者 128 个线程的测试然后在测试期间记录 MySQL 数据库的 Threads_running 状态值。在第11章将讨论这个指标对容量规划的影响。 可扩展性 在系统的业务压力可能发生变化的情况下测试可扩展性就非常必要了。第11章将更进一步讨论可扩展性的话题。简单地说可扩展性指的是给系统增加一倍的工作在理想情况下就能获得两倍的结果即吞吐量增加一倍。或者说给系统增加一倍的资源比如两倍的CPU数就可以获得两倍的吞吐量。 当然同时性能响应时间也必须在可以接受的范围内。大多数系统是无法做到如此理想的线性扩展的。随着压力的变化吞吐量和性能都可能越来越差。 可扩展性指标对于容量规范非常有用它可以提供其他测试无法提供的信息来帮助发现应用的瓶颈。比如如果系统是基于单个用户的响应时间测试这是一个很糟糕的测试策略设计的虽然测试的结果很好但当并发度增加时系统的性能有可能变得非常糟糕。而一个基于不断增加用户连接的情况下的响应时间测试则可以发现这个问题。 一些任务比如从细粒度数据创建汇总表的批量工作需要的是周期性的快速响应时间。当然也可以测试这些任务纯粹的响应时间但要注意考虑这些任务之间的相互影响。批量工作可能导致相互之间有影响的查询性能变差反之亦然。
归根结底应该测试那些对用户来说最重要的指标。因此应该尽可能地去收集一些需求比如什么样的响应时间是可以接受的期待多少的并发性等等。然后基于这些需求来设计基准测试避免目光短浅地只关注部分指标而忽略其他指标。
2.3 基准测试方法
一些可能导致测试结果无用或者不精确的常见错误
使用真实数据的子集而不是全集。例如应用需要处理几百GB的数据但测试只有1GB数据或者只使用当前数据进行测试却希望模拟未来业务大幅度增长后的情况。使用错误的数据分布。例如使用均匀分布的数据测试而系统的真实数据有很多热点区域随机生成的测试数据通常无法模拟真实的数据分布。使用不真实的分布参数例如假定所有用户的个人信息profile都会被平均地读取。在多用户场景中只做单用户的测试。在单服务器上测试分布式应用。与真实用户行为不匹配。例如 Web 页面中的“思考时间”。真实用户在请求到一个页面后会阅读一段时间而不是不停顿地一个接一个点击相关链接。反复执行同一个查询。真实的查询是不尽相同的这可能会导致缓存命中率降低。而反复执行同一个查询在某种程度上会全部或者部分缓存结果。没有检查错误。如果测试的结果无法得到合理的解释比如一个本应该很慢的查询突然变快了就应该检查是否有错误产生。否则可能只是测试了 MySQL 检测语法错误的速度了。基准测试完成后一定要检查一下错误日志这应当是基本的要求。忽略了系统预热warm up的过程。例如系统重启后马上进行测试。有时候需要了解系统重启后需要多长时间才能达到正常的性能容量要特别留意预热的时长。反过来说如果要想分析正常的性能需要注意若基准测试在重启以后马上启动则缓存是冷的、还没有数据这时即使测试的压力相同得到的结果也和缓存已经装满数据时是不同的。使用默认的服务器配置。第3章将详细地讨论服务器的优化配置。测试时间太短。基准测试需要持续一定的时间。后面会继续讨论这个话题。
如果其他条件相同就应努力使测试过程尽可能地接近真实应用的情况。
2.3.1 设计和规划基准测试
规划基准测试的第一步是提出问题并明确目标。然后决定是采用标准的基准测试还是设计专用的测试。
如果采用标准的基准测试应该确认选择了合适的测试方案。例如不要使用 TPC-H 测试电子商务系统。在 TPC 的定义中“TPC-H 是即席查询和决策支持型应用的基准测试”因此不适合用来测试 OLTP 系统。
设计专用的基准测试是很复杂的往往需要一个迭代的过程。首先需要获得生产数据集的快照并且该快照很容易还原以便进行后续的测试。
然后针对数据运行查询。可以建立一个单元测试集作为初步的测试并运行多遍。但是这和真实的数据库环境还是有差别的。更好的办法是选择一个有代表性的时间段比如高峰期的一个小时或者一整天记录生产系统上的所有查询。如果时间段选得比较小则可以选择多个时间段。这样有助于覆盖整个系统的活动状态例如每周报表的查询、或者非峰值时间运行的批处理作业。当然做这么多的前提是希望获得完美的基准测试结果实际情况通常不会很顺利。
可以在不同级别记录查询。例如如果是集成式full-stack基准测试可以记录Web服务器上的 HTTP 请求也可以打开 MySQL 的查询日志Query Log。倘若要重演这些查询就要确保创建多线程来并行执行而不是单个线程线性地执行。对日志中的每个连接都应该创建独立的线程而不是将所有的查询随机地分配到一些线程中。查询日志中记录了每个查询是在哪个连接中执行的。
即使不需要创建专用的基准测试详细地写下测试规划也是必需的。测试可能要多次反复运行因此需要精确地重现测试过程。而且也应该考虑到未来执行下一轮测试时可能已经不是同一个人了。即使还是同一个人也有可能不会确切地记得初次运行时的情况。测试规划应该记录测试数据、系统配置的步骤、如何测量和分析结果以及预热的方案等。
应该建立将参数和结果文档化的规范每一轮测试都必须进行详细记录。文档规范可以很简单比如采用电子表格spreadsheet或者记事本形式也可以是复杂的自定义的数据库。需要记住的是经常要写一些脚本来分析测试结果因此如果能够不用打开电子表格或者文本文件等额外操作当然是更好的。
2.3.2 基准测试应该运行多长时间
基准测试应该运行足够长的时间这一点很重要。如果需要测试系统在稳定状态时的性能那么当然需要在稳定状态下测试并观察。
有时候无法确认测试需要运行多长的时间才足够。如果是这样可以让测试一直运行持续观察直到确认系统已经稳定。一个简单的测试规则就是等系统看起来稳定的时间至少等于系统预热的时间。
一个常见的错误的测试方式是只执行一系列短期的测试比如每次60秒并在此测试的基础上去总结系统的性能。
2.3.3 获取系统性能和状态
在执行基准测试时需要尽可能多地收集被测试系统的信息。最好为基准测试建立一个目录并且每执行一轮测试都创建单独的子目录将测试结果、配置文件、测试指标、脚本和其他相关说明都保存在其中。即使有些结果不是目前需要的也应该先保存下来。多余一些数据总比缺乏重要的数据要好而且多余的数据以后也许会用得着。需要记录的数据包括系统状态和性能指标诸如 CPU 使用率、磁盘 I/O、网络流量统计、SHOW GLOBAL STATUS计数器等。
2.3.4 获得准确的测试结果
获得准确测试结果的最好办法是回答一些关于基准测试的基本问题是否选择了正确的基准测试是否为问题收集了相关的数据是否采用了错误的测试标准
接着确认测试结果是否可重复。每次重新测试之前要确保系统的状态是一致的。如果是非常重要的测试甚至有必要每次测试都重启系统。一般情况下需要测试的是经过预热的系统还需要确保预热的时间足够长请参考前面关于基准测试需要运行多长时间的内容、是否可重复。如果预热采用的是随机查询那么测试结果可能就是不可重复的。
如果测试的过程会修改数据或者schema那么每次测试前需要利用快照还原数据。数据的碎片度和在磁盘上的分布都可能导致测试是不可重复的。一个确保物理磁盘数据的分布尽可能一致的办法是每次都进行快速格式化并进行磁盘分区复制。
要注意很多因素包括外部的压力、性能分析和监控系统、详细的日志记录、周期性作业以及其他一些因素都会影响到测试结果。一个典型的案例就是测试过程中突然有cron定时作业启动或者正处于一个巡查读取周期Patrol Read cycle抑或RAID卡启动了定时的一致性检查等。要确保基准测试运行过程中所需要的资源是专用于测试的。
每次测试中修改的参数应该尽量少。变量控制的理想情况为一个变量。
一般情况下都是通过迭代逐步地修改基准测试的参数而不是每次运行时都做大量的修改。举个例子如果要通过调整参数来创造一个特定行为可以通过使用分治法divide-and-conquer每次运行时将参数对分减半来找到正确的值。
很多基准测试都是用来做预测系统迁移后的性能的比如从 Oracle 迁移到 MySQL 。这种测试通常比较麻烦通常需要重新设计 MySQL 的 schema 和查询在某些情况下比如建立一个跨平台的应用时可能想知道同一条查询是如何在两个平台运行的不过这种情况并不多见。
另外基于MySQL的默认配置的测试没有什么意义因为默认配置是基于消耗很少内存的极小应用的。有时候可以看到一些 MySQL 和其他商业数据库产品的对比测试结果很让人尴尬可能就是 MySQL 采用了默认配置的缘故。让人无语的是这样明显有误的测试结果还容易变成头条新闻。
固态存储SSD 或者 PCI-E 卡给基准测试带来了很大的挑战第 9 章将进一步讨论。
最后如果测试中出现异常结果不要轻易当作坏数据点而丢弃。应该认真研究并找到产生这种结果的原因。
2.3.5 运行基准测试并分析结果
一旦准备就绪就可以着手基准测试收集和分析数据了。
通常来说自动化基准测试是个好主意。这样做可以获得更精确的测试结果。因为自动化的过程可以防止测试人员偶尔遗漏某些步骤或者误操作。另外也有助于归档整个测试过程。
自动化的方式有很多可以是一个 Makefile 文件或者一组脚本。脚本语言可以根据需要选择shell、PHP、Perl 等都可以。要尽可能地使所有测试过程都自动化包括装载数据、系统预热、执行测试、记录结果等。 一旦设置了正确的自动化操作基准测试将成为一步式操作。如果只是针对某些应用做一次性的快速验证测试可能就没必要做自动化。但只要未来可能会引用到测试结果建议都尽量地自动化。否则到时候可能就搞不清楚是如何获得这个结果的也不记得采用了什么参数这样就很难再通过测试重现结果了。 基准测试通常需要运行多次。具体需要运行多少次要看对结果的记分方式以及测试的重要程度。要提高测试的准确度就需要多运行几次。一般在测试的实践中可以取最好的结果值或者所有结果的平均值抑或从五个测试结果里取最好三个值的平均值。可以根据需要更进一步精确化测试结果。还可以对结果使用统计方法确定置信区间confidence interval等。不过通常来说不会用到这种程度的确定性结果。只要测试的结果能满足目前的需求简单地运行几轮测试看看结果的变化就可以了。如果结果变化很大可以再多运行几次或者运行更长的时间这样都可以获得更确定的结果。
获得测试结果后还需要对结果进行分析也就是说要把“数字”变成“知识”。最终的目的是回答在设计测试时的问题。理想情况下可以获得诸如“升级到 4 核 CPU 可以在保持响应时间不变的情况下获得超过50的吞吐量增长”或者“增加索引可以使查询更快”的结论。
如何从数据中抽象出有意义的结果依赖于如何收集数据。通常需要写一些脚本来分析数据这不仅能减轻分析的工作量而且和自动化基准测试一样可以重复运行并易于文档化。
2.3.6 绘图的重要性
最简单有效的图形就是将性能指标按照时间顺序绘制。通过图形可以立刻发现一些问题而这些问题在原始数据中却很难被注意到。或许你会坚持看测试工具打印出来的平均值或其他汇总过的信息但平均值有时候是没有用的它会掩盖掉一些真实情况。幸运的是前面写的脚本的输出都可以定制作为 gnuplot 或者 R 绘图的数据来源。假设使用 gnuplot假设输出的数据文件名是 QPS-per-5-seconds gnuplot plot QPS-per-5-seconds using 5 w lines titleQPS该gnuplot命令将文件的第五列 qps 数据绘成图形图的标题是 QPS。图2-2是绘制出来的结果图。
假设MySQL数据正在遭受“疯狂刷新furious flushing”的问题在刷新落后于检查点时会阻塞所有的活动从而导致吞吐量严重下跌。95的响应时间和平均响应时间指标都无法发现这个问题也就是说这两个指标掩盖了问题。但图形会显示出这个周期性的问题请参考图2-3。
图2-3显示的是每分钟新订单的交易量NOTPMnew-order transactions per minute。从曲线可以看到明显的周期性下降但如果从平均值点状虚线来看波动很小。一开始的低谷是由于系统的缓存是空的而后面其他的下跌则是由于系统刷新脏块到磁盘导致。如果没有图形要发现这个趋势会比较困难。 这种性能尖刺在压力大的系统比较常见需要调查原因。在这个案例中是由于使用了旧版本的 InnoDB 引擎脏块的刷新算法性能很差。但这个结论不能是想当然的需要认真地分析详细的性能统计。在性能下跌时SHOW ENGINE INNODB STATUS的输出是什么SHOW FULL PROCESSLIST的输出是什么应该可以发现 InnoDB 在持续地刷新脏块并且阻塞了很多状态是“waiting on query cache lock”的线程或者其他类似的现象。在执行基准测试的时候要尽可能地收集更多的细节数据然后将数据绘制成图形这样可以帮助快速地发现问题。
2.4 基准测试工具
回忆一下前文提供的两种测试类型集成式测试和单组件式测试。毫不奇怪有些工具是针对整个应用进行测试也有些工具是针对 MySQL 或者其他组件单独进行测试的。集成式测试通常是获得整个应用概况的最佳手段。已有的集成式测试工具如下所示。 ab ab 是一个 Apache HTTP 服务器基准测试工具。它可以测试 HTTP 服务器每秒最多可以处理多少请求。如果测试的是 Web 应用服务这个结果可以转换成整个应用每秒可以满足多少请求。这是个非常简单的工具用途也有限只能针对单个 URL 进行尽可能快的压力测试。关于 ab 的更多信息可以参考 http://httpd.apache.org/docs/2.0/programs/ab.html 。 http_load 这个工具概念上和 ab 类似也被设计为对 Web 服务器进行测试但比 ab 要更加灵活。可以通过一个输入文件提供多个 URLhttp_load 在这些 URL 中随机选择进行测试。也可以定制http_load使其按照时间比率进行测试而不仅仅是测试最大请求处理能力。更多信息请参考 http://www.acme.com/software/http_load/ 。 JMeter JMeter 是一个Java 应用程序可以加载其他应用并测试其性能。它虽然是设计用来测试Web应用的但也可以用于测试其他诸如 FTP 服务器或者通过 JDBC 进行数据库查询测试。 JMeter 比 ab 和 http_load 都要复杂得多。例如它可以通过控制预热时间等参数更加灵活地模拟真实用户的访问。JMeter 拥有绘图接口带有内置的图形化处理的功能还可以对测试进行记录然后离线重演测试结果。更多信息请参考http://jakarta.apache.org/jmeter/。
2.4.2 单组件式测试工具
有一些有用的工具可以测试 MySQL 和基于 MySQL 的系统的性能。2.5 节将演示如何利用这些工具进行测试。 mysqlslap mysqlslaphttp://dev.mysql.com/doc/refman/5.1/en/mysqlslap.html可以模拟服务器的负载并输出计时信息。它包含在 MySQL 5.1 的发行包中应该在 MySQL 4.1 或者更新的版本中都可以使用。测试时可以执行并发连接数并指定SQL语句可以在命令行上执行也可以把 SQL 语句写入到参数文件中。如果没有指定 SQL 语句mysqlslap 会自动生成查询 schema 的 SELECT 语句。 MySQL Benchmark Suitesql-bench 在 MySQL 的发行包中也提供了一款自己的基准测试套件可以用于在不同数据库服务器上进行比较测试。它是单线程的主要用于测试服务器执行查询的速度。结果会显示哪种类型的操作在服务器上执行得更快。 这个测试套件的主要好处是包含了大量预定义的测试容易使用所以可以很轻松地用于比较不同存储引擎或者不同配置的性能测试。其也可以用于高层次测试比较两个服务器的总体性能。当然也可以只执行预定义测试的子集例如只测试 UPDATE 的性能。这些测试大部分是 CPU 密集型的但也有些短时间的测试需要大量的磁盘 I/O 操作。 这个套件的最大缺点主要有它是单用户模式的测试的数据集很小且用户无法使用指定的数据并且同一个测试多次运行的结果可能会相差很大。因为是单线程且串行执行的所以无法测试多 CPU 的能力只能用于比较单 CPU 服务器的性能差别。使用这个套件测试数据库服务器还需要 Perl 和 BDB 的支持相关文档请参考 http://dev.mysql.com/doc/en/mysql-benchmarks.html/ 。 Super Smack Super Smackhttp://vegan.net/tony/supersmack/是一款用于 MySQL 和 PostgreSQL 的基准测试工具可以提供压力测试和负载生成。这是一个复杂而强大的工具可以模拟多用户访问可以加载测试数据到数据库并支持使用随机数据填充测试表。测试定义在“smack”文件中smack 文件使用一种简单的语法定义测试的客户端、表、查询等测试要素。 Database Test Suite Database Test Suite 是由开源软件开发实验室OSDLOpen Source Development Labs设计的发布在 SourceForge 网站http://sourceforge.net/projects/osdldbt/上这是一款类似某些工业标准测试的测试工具集例如由事务处理性能委员会TPCTransaction Processing Performance Council制定的各种标准。特别值得一提的是其中的 dbt2 就是一款免费的 TPC-C OLTP 测试工具未认证。之前本书作者经常使用该工具不过现在已经使用自己研发的专用于 MySQL 的测试工具替代了。 Percona’s TPCC-MySQL Tool 我们开发了一个类似 TPC-C 的基准测试工具集其中有部分是专门为 MySQL 测试开发的。在评估大压力下MySQL的一些行为时我们经常会利用这个工具进行测试简单的测试一般会采用 sysbench 替代。该工具的源代码可以在 https://launchpad.net/perconatools 下载在源码库中有一个简单的文档说明。 sysbench 推荐 sysbenchhttps://launchpad.net/sysbench是一款多线程系统压测工具。它可以根据影响数据库服务器性能的各种因素来评估系统的性能。例如可以用来测试文件 I/O、操作系统调度器、内存分配和传输速度、POSIX 线程以及数据库服务器等。sysbench 支持 Lua 脚本语言http://www.lua.orgLua 对于各种测试场景的设置可以非常灵活。sysbench 是我们非常喜欢的一种全能测试工具支持 MySQL 、操作系统和硬件的硬件测试。
2.5 基准测试案例
2.5.1 http_load
下面通过一个简单的例子来演示如何使用 http_load 。首先创建一个 urls.txt 文件输入如下的URL
http://www.mysqlperformanceblog.com/
http://www.mysqlperformanceblog.com/page/2/
http://www.mysqlperformanceblog.com/mysql-patches/
http://www.mysqlperformanceblog.com/mysql-performance-presentations/
http://www.mysqlperformanceblog.com/2006/09/06/slow-query-log-analyzes-tools/http_load最简单的用法就是循环请求给定的 URL 列表。测试程序将以最快的速度请求这些URL
$ http_load -parallel 1 -seconds 10 urls.txt
19 fetches, 1 max parallel, 837929 bytes, in 10.0003 seconds
44101.5 mean bytes/connection
1.89995 fetches/sec, 83790.7 bytes/sec
msecs/connect: 41.6647 mean, 56.156 max, 38.21 min
msecs/first-response: 320.207 mean, 508.958 max, 179.308 min
HTTP response codes:
code 200 - 19测试的结果很容易理解只是简单地输出了请求的统计信息。下面是另外一个稍微复杂的测试还是尽可能快地循环请求给定的 URL 列表不过模拟同时有五个并发用户在进行请求
$ http_load -parallel 5 -seconds 10 urls.txt
94 fetches, 5 max parallel, 4.75565e06 bytes, in 10.0005 seconds
50592 mean bytes/connection
9.39953 fetches/sec, 475541 bytes/sec
msecs/connect: 65.1983 mean, 169.991 max, 38.189 min
msecs/first-response: 245.014 mean, 993.059 max, 99.646 min
HTTP response codes:
code 200 - 94另外除了测试最快的速度也可以根据预估的访问请求率比如每秒 5 次来做压力模拟测试。
$ http_load -rate 5 -seconds 10 urls.txt
48 fetches, 4 max parallel, 2.50104e06 bytes, in 10 seconds
52105 mean bytes/connection
4.8 fetches/sec, 250104 bytes/sec
msecs/connect: 42.5931 mean, 60.462 max, 38.117 min
msecs/first-response: 246.811 mean, 546.203 max, 108.363 min
HTTP response codes:
code 200 - 48最后还可以模拟更大的负载可以将访问请求率提高到每秒 20 次请求。请注意连接和请求响应时间都会随着负载的提高而增加。
$ http_load -rate 20 -seconds 10 urls.txt
111 fetches, 89 max parallel, 5.91142e06 bytes, in 10.0001 seconds
53256.1 mean bytes/connection
11.0998 fetches/sec, 591134 bytes/sec
msecs/connect: 100.384 mean, 211.885 max, 38.214 min
msecs/first-response: 2163.51 mean, 7862.77 max, 933.708 min
HTTP response codes:
code 200 -- 1112.5.2 MySQL基准测试套件
MySQL 基准测试套件MySQL Benchmark Suite 由一组基于 Perl 开发的基准测试工具组成。在 MySQL 安装目录下的 sql-bench 子目录中包含了该工具。比如在 Debian GNU/Linux 系统上默认的路径是/usr/share/mysql/sql-bench。
在用这个工具集测试前应该读一下README文件了解使用方法和命令行参数说明。如果要运行全部测试可以使用如下的命令
$ cd /usr/share/mysql/sql-bench/
sql-bench$ ./run-all-tests --servermysql --userroot --log --fast
Test finished. You can find the result in:
output/RUN-mysql_fast-Linux_2.4.18_686_smp_i686运行全部测试需要比较长的时间有可能会超过一个小时其具体长短依赖于测试的硬件环境和配置。如果指定了--log命令行则可以监控到测试的进度。测试的结果都保存在 output 子目录中每项测试的结果文件中都会包含一系列的操作计时信息。
2.5.3 sysbench
sysbench 可以执行多种类型的基准测试它不仅设计用来测试数据库的性能也可以测试运行数据库的服务器的性能。实际上Peter 和 Vadim 最初设计这个工具是用来执行 MySQL 性能测试的尽管并不能完成所有的 MySQL 基准测试。下面先演示一些非 MySQL 的测试场景来测试各个子系统的性能这些测试可以用来评估系统的整体性能瓶颈。后面再演示如何测试数据库的性能。
强烈建议大家都能熟悉 sysbench 测试在MySQL用户的工具包中这应该是最有用的工具之一。尽管有其他很多测试工具可以替代 sysbench 的某些功能但那些工具有时候并不可靠获得的结果也不一定和 MySQL 性能相关。例如I/O 性能测试可以用 iozone、bonnie 等一系列工具但需要注意设计场景以便可以模拟 InnoDB 的磁盘 I/O 模式。而 sysbench 的 I/O 测试则和 InnoDB 的 I/O 模式非常类似所以 fileio 选项是非常好用的。
sysbench 的CPU基准测试
最典型的子系统测试就是 CPU 基准测试。该测试使用 64 位整数测试计算素数直到某个最大值所需要的时间。下面的例子将比较两台不同的 GNU/Linux 服务器上的测试结果。第一台机器的 CPU 配置如下
[server1 ~]$ cat /proc/cpuinfo
...
model name : AMD Opteron(tm) Processor 246
stepping : 1
cpu MHz : 1992.857
cache size : 1024 KB在这台服务器上运行如下的测试
[server1 ~]$ sysbench --testcpu --cpu-max-prime20000 run
sysbench v0.4.8: multithreaded system evaluation benchmark
...
Test execution summary: total time: 121.7404s第二台服务器配置了不同的 CPU
[server2 ~]$ cat /proc/cpuinfo
...
model name : Intel(R) Xeon(R) CPU 5130 2.00GHz
stepping : 6
cpu MHz : 1995.005测试结果如下
[server1 ~]$ sysbench --testcpu --cpu-max-prime20000 run
sysbench v0.4.8: multithreaded system evaluation benchmark
...
Test execution summary: total time: 61.8596s测试的结果简单打印出了计算出素数的时间很容易进行比较。在上面的测试中第二台服务器的测试结果显示比第一台快两倍。
sysbench 的文件 I/O 基准测试
文件I/Ofileio基准测试可以测试系统在不同 I/O 负载下的性能。这对于比较不同的硬盘驱动器、不同的 RAID 卡、不同的 RAID 模式都很有帮助。可以根据测试结果来调整 I/O 子系统。文件 I/O 基准测试模拟了很多 InnoDB 的 I/O 特性。
测试的第一步是准备prepare阶段生成测试用到的数据文件生成的数据文件至少要比内存大。如果文件中的数据能完全放入内存中则操作系统缓存大部分的数据导致测试结果无法体现I/O密集型的工作负载。首先通过下面的命令创建一个数据集
$ sysbench --testfileio --file-total-size150G prepare这个命令会在当前工作目录下创建测试文件后续的运行run阶段将通过读写这些文件进行测试。第二步就是运行run阶段针对不同的I/O类型有不同的测试选项 seqwr 顺序写入。 seqrewr 顺序重写。 seqrd 顺序读取。 rndrd 随机读取。 rndwr 随机写入。 rdnrw 混合随机读/写。
下面的命令运行文件 I/O 混合随机读/写基准测试
$ sysbench --testfileio --file-total-size150G --file-test-moderndrw/
--init-rngon--max-time300--max-requests0 run结果如下
sysbench v0.4.8: multithreaded system evaluation benchmarkRunning the test with following options:
Number of threads: 1
Initializing random number generator from timer.Extra file open flags: 0
128 files, 1.1719Gb each
150Gb total file size
Block size 16Kb
Number of random requests for random IO: 10000
Read/Write ratio for combined random IO test: 1.50
Periodic FSYNC enabled, calling fsync() each 100 requests.
Calling fsync() at the end of test, Enabled.
Using synchronous I/O mode
Doing random r/w test
Threads started!
Time limit exceeded, exiting...
Done.Operations performed: 40260 Read, 26840 Write, 85785 Other 152885 Total
Read 629.06Mb Written 419.38Mb Total transferred 1.0239Gb (3.4948Mb/sec)
223.67 Requests/sec executedTest execution summary:
total time: 300.0004s
total number of events: 67100
total time taken by event execution: 254.4601
per-request statistics:
min: 0.0000s
avg: 0.0038s
max: 0.5628s
approx. 95 percentile: 0.0099s
Threads fairness:
events (avg/stddev): 67100.0000/0.00
execution time (avg/stddev): 254.4601/0.00输出结果中包含了大量的信息。和 I/O 子系统密切相关的包括每秒请求数和总吞吐量。在上述例子中每秒请求数是 223.67 Requests/sec吞吐量是 3.4948 MB/sec。另外时间信息也非常有用尤其是大约 95 的时间分布。这些数据对于评估磁盘性能十分有用。
测试完成后运行清除cleanup操作删除第一步生成的测试文件
$ sysbench --testfileio --file-total-size150G cleanupsysbench 的 OLTP 基准测试
OLTP 基准测试模拟了一个简单的事务处理系统的工作负载。下面的例子使用的是一张超过百万行记录的表第一步是先生成这张表
$ sysbench --testoltp --oltp-table-size1000000 --mysql-dbtest/
--mysql-userroot prepare
sysbench v0.4.8: multithreaded system evaluation benchmarkNo DB drivers specified, using mysql
Creating table sbtest...
Creating 1000000 records in table sbtest...生成测试数据只需要上面这条简单的命令即可。接下来可以运行测试这个例子采用了 8 个并发线程只读模式测试时长 60 秒
$ sysbench --testoltp --oltp-table-size1000000 --mysql-dbtest --mysql-userroot/
--max-time60 --oltp-read-onlyon --max-requests0 --num-threads8 run
sysbench v0.4.8: multithreaded system evaluation benchmarkNo DB drivers specified, using mysql
WARNING: Preparing of BEGIN is unsupported, using emulation
(last message repeated 7 times)
Running the test with following options:
Number of threads: 8Doing OLTP test.
Running mixed OLTP test
Doing read-only test
Using Special distribution (12 iterations, 1 pct of values are returned in 75 pct
cases)
Using BEGIN for starting transactions
Using auto_inc on the id column
Threads started!
Time limit exceeded, exiting...
(last message repeated 7 times)
Done.OLTP test statistics:
queries performed:
read: 179606
write: 0
other: 25658
total: 205264
transactions: 12829 (213.07 per sec.)
deadlocks: 0 (0.00 per sec.)
read/write requests: 179606 (2982.92 per sec.)
other operations: 25658 (426.13 per sec.)Test execution summary:
total time: 60.2114s
total number of events: 12829
total time taken by event execution: 480.2086
per-request statistics:
min: 0.0030s
avg: 0.0374s
max: 1.9106s
approx. 95 percentile: 0.1163s
Threads fairness:
events (avg/stddev): 1603.6250/70.66
execution time (avg/stddev): 60.0261/0.06如上所示结果中包含了相当多的信息。其中最有价值的信息如下
总的事务数。每秒事务数。时间统计信息最小、平均、最大响应时间以及 95 百分比响应时间。线程公平性统计信息thread-fairness用于表示模拟负载的公平性。
这个例子使用的是 sysbench 的第 4 版在 SourceForge.net 可以下载到这个版本的编译好的可执行文件。也可以从 Launchpad 下载最新的第 5 版的源代码自行编译这是一件简单、有用的事情这样就可以利用很多新版本的特性包括可以基于多个表而不是单个表进行测试可以每隔一定的间隔比如 10 秒打印出吞吐量和响应的结果。这些指标对于理解系统的行为非常重要。
sysbench 的其他特性
sysbench 还有一些其他的基准测试但和数据库性能没有直接关系。 memory 内存memory 测试内存的连续读写性能。 线程thread 测试线程调度器的性能。对于高负载情况下测试线程调度器的行为非常有用。 互斥锁mutex 测试互斥锁mutex的性能方式是模拟所有线程在同一时刻并发运行并都短暂请求互斥锁互斥锁mutex是一种数据结构用来对某些资源进行排他性访问控制防止因并发访问导致问题。 顺序写seqwr 测试顺序写的性能。这对于测试系统的实际性能瓶颈很重要。可以用来测试RAID控制器的高速缓存的性能状况如果测试结果异常则需要引起重视。例如如果RAID控制器写缓存没有电池保护而磁盘的压力达到了 3000 次请求/秒就是一个问题数据可能是不安全的。
另外除了指定测试模式参数--test外sysbench 还有其他很多参数比如 --num-threads、--max-requests和--max-time参数更多信息请查阅相关文档。
2.5.4 数据库测试套件中的 dbt2 TPC-C 测试
数据库测试套件Database Test Suite中的 dbt2 是一款免费的 TPC-C 测试工具。TPC-C 是 TPC 组织发布的一个测试规范用于模拟测试复杂的在线事务处理系统OLTP。它的测试结果包括每分钟事务数tpmC以及每事务的成本Price/tpmC。这种测试的结果非常依赖硬件环境所以公开发布的 TPC-C 测试结果都会包含具体的系统硬件配置信息。 dbt2 并不是真正的 TPC-C 测试它没有得到 TPC 组织的认证它的结果不能直接跟 TPC-C 的结果做对比。而且本书作者开发了一款比 dbt2 更好的测试工具详细情况见 2.5.5 节。 例子略自己去看书。
注意对于I/O密集型的基准测试太短的持续时间会导致错误的结果因为系统可能还没有足够的时间对缓存进行预热。而对于CPU密集型的基准测试这个时间又不应该设置得太长否则生成的数据量过大可能转变成I/O密集型。
2.5.5 Percona的TPCC-MySQL测试工具
尽管 sysbench 的测试很简单并且结果也具有可比性但毕竟无法模拟真实的业务压力。相比而言TPC-C 测试则能模拟真实压力。2.5.4 节谈到的 dbt2 是 TPC-C 的一个很好的实现但也还有一些不足之处。为了满足很多大型基准测试的需求本书的作者重新开发了一款新的类 TPC-C 测试工具代码放在 Launchpad 上可以通过如下地址获取 https://code.launchpad.net/~percona-dev/perconatools/tpcc-mysql 其中包含了一个 README 文件说明了如何编译。该工具使用很简单但测试数据中的仓库数量很多可能需要用到其中的并行数据加载工具来加快准备测试数据集的速度否则这一步会花费很长时间。
使用这个测试工具需要创建数据库和表结构、加载数据、执行测试三个步骤。数据库和表结构通过包含在源码中的 SQL 脚本创建。加载数据通过用 C 写的 tpcc_load 工具完成该工具需要自行编译。加载数据需要执行一段时间并且会产生大量的输出信息一般都应该将程序输出重定向到文件中这里尤其应该如此否则可能丢失滚动的历史信息。下面的例子显示了配置过程创建了一个小型五个仓库的测试数据集数据库名为 tpcc5 。
$ ./tpcc_load localhost tpcc5 username p4ssword 5/b
*************************************
*** ###easy### TPC-C Data Loader ***
*************************************
Parameters
[server]: localhost
[port]: 3306
[DBname]: tpcc5
[user]: username
[pass]: p4ssword
[warehouse]: 5
TPCC Data Load Started...
Loading Item
.................................................. 5000
.................................................. 10000
.................................................. 15000[output snipped for brevity]Loading Orders for D10, W 5
.......... 1000
.......... 2000
.......... 3000
Orders Done....DATA LOADING COMPLETED SUCCESSFULLY.然后使用 tpcc_start 工具开始执行基准测试。其同样会产生很多输出信息还是建议重定向到文件中。下面是一个简单的示例使用五个线程操作五个仓库30 秒预热时间30 秒测试时间
$ ./tpcc_start localhost tpcc5 username p4ssword 5 5 30 30
***************************************
*** ###easy### TPC-C Load Generator ***
***************************************
Parameters
[server]: localhost
[port]: 3306
[DBname]: tpcc5
[user]: username
[pass]: p4ssword
[warehouse]: 5
[connection]: 5
[rampup]: 30 (sec.)
[measure]: 30 (sec.)RAMP-UP TIME.(30 sec.)MEASURING START.10, 63(0):0.40, 63(0):0.42, 7(0):0.76, 6(0):2.60, 6(0):0.17
20, 75(0):0.40, 74(0):0.62, 7(0):0.04, 9(0):2.38, 7(0):0.75
30, 83(0):0.22, 84(0):0.37, 9(0):0.04, 7(0):1.97, 9(0):0.80STOPPING THREADS.....RT Histogram1.New-Order
2.Payment
3.Order-Status
4.Delivery
5.Stock-Level90th Percentile RT (MaxRT)
New-Order : 0.37 (1.10)
Payment : 0.47 (1.24)
Order-Status : 0.06 (0.96)
Delivery : 2.43 (2.72)
Stock-Level : 0.75 (0.79)Raw Results
[0] sc:221 lt:0 rt:0 fl:0
[1] sc:221 lt:0 rt:0 fl:0
[2] sc:23 lt:0 rt:0 fl:0
[3] sc:22 lt:0 rt:0 fl:0
[4] sc:22 lt:0 rt:0 fl:0
in 30 sec.Raw Results2(sum ver.)
[0] sc:221 lt:0 rt:0 fl:0
[1] sc:221 lt:0 rt:0 fl:0
[2] sc:23 lt:0 rt:0 fl:0
[3] sc:22 lt:0 rt:0 fl:0
[4] sc:22 lt:0 rt:0 fl:0Constraint Check (all must be [OK])
[transaction percentage]
Payment: 43.42% (43.0%) [OK]
Order-Status: 4.52% ( 4.0%) [OK]
Delivery: 4.32% ( 4.0%) [OK]
Stock-Level: 4.32% ( 4.0%) [OK]
[response time (at least 90% passed)]
New-Order: 100.00% [OK]
Payment: 100.00% [OK]
Order-Status: 100.00% [OK]
Delivery: 100.00% [OK]
Stock-Level: 100.00% [OK]TpmC
442.000 TpmC最后一行就是测试的结果每分钟执行完的事务数。如果紧挨着最后一行前发现有异常结果输出比如有关于约束检查的信息那么可以检查一下响应时间的直方图或者通过其他详细输出信息寻找线索。当然最好是能使用本章前面提到的一些脚本这样就可以很容易获得测试执行期间的详细的诊断数据和性能数据。
2.6 总结
每个 MySQL 的使用者都应该了解一些基准测试的知识。基准测试不仅仅是用来解决业务问题的一种实践行动也是一种很好的学习方法。学习如何将问题分解成可以通过基准测试来获得答案的方法就和在数学课上从文字题目中推导出方程式一样。首先正确地描述问题之后选择合适的基准测试来回答问题设置基准测试的持续时间和参数运行测试收集数据分析结果数据这一系列的训练可以帮助你成为更好的 MySQL 用户。
如果你还没有做过基准测试那么建议至少要熟悉 sysbench。 可以先学习如何使用 oltp 和 fileio 测试。oltp 基准测试可以很方便地比较不同系统的性能。另一方面文件系统和磁盘基准测试则可以在系统出现问题时有效地诊断和隔离异常的组件。通过这样的基准测试我们多次发现了一些数据库管理员的说法存在问题比如 SAN 存储真的出现了一块坏盘或者 RAID 控制器的缓存策略的配置并不是像工具中显示的那样。通过对单块磁盘进行基准测试如果发现每秒可以执行 14000 次随机读那要么是碰到了严重的错误要么是配置出现了问题。 一块机械磁盘每秒只能执行几百次的随机读操作因为寻道操作是需要时间的。 如果经常执行基准测试那么制定一些原则是很有必要的。选择一些合适的测试工具并深入地学习。可以建立一个脚本库用于配置基准测试收集输出结果、系统性能和状态信息以及分析结果。使用一种熟练的绘图工具如 gnuplot 或者 R 不用浪费时间使用电子表格它们既笨重速度又慢。尽量早和多地使用绘图的方式来发现基准测试和系统中的问题和错误。你的眼睛是比任何脚本和自动化工具都更有效的发现问题的工具。