zoukankan      html  css  js  c++  java
  • 9-MySQL DBA笔记-测试实践

    第9章 测试实践
    在第8章中介绍了测试所需要的理论知识,本章将为读者讲述实际的测试过程。
    实际测试一般包括硬件测试、MySQL基准测试及应用服务压力测试,下面将分别讲述这三方面的内容。
    此外,测试工具的选择也很重要,本章将为读者介绍两个常用的工具sysbench和mysqlslap。
    9.1 硬件测试
    9.1.1 概述
    有时我们出于一些原因,需要进行硬件的测试。
    比如,软件架构很复杂,难以模拟,这时我们可以大致测量一些硬件指标,建立比较基本的性能和容量模型。
    比如,在升级硬件的时候,往往不会选择升级所有硬件,而是更着重于首先升级系统紧缺的资源,例如I/O,那么这时就需要专门针对不同的硬件配置,来测试I/O的提升效果。
    再比如,硬件厂商往往夸大其词,这时我们就需要运用自己认为可靠的工具去实际验证,确认新的硬件在一些关键指标上是否有大幅度的提升。
    现实中,硬件和数据库的测试工具并没有划分得很清晰,一些数据库测试工具,本身就可以对各种硬件资源进行压力测试。
    比如sysbench,既可以测试数据库,又可以用来测试CPU、内存等硬件资源。
    本书将主要关注Linux下的软硬件测试。
    一些需要测量的硬件有:内存、CPU、磁盘、网卡、网络等。
    网上也有很多优秀的开源测试工具,这里仅列出一些常用的测试工具。
    内存测试的工具有sysbench、stream、RamSpeed、stress等。
    CPU测试的工具有sysbench、cpuburn、stress等。
    磁盘测试的工具有sysbench、iozone等。

    9.1.2 CPU测试
    sysbench命令通过进行素数运算来测试CPU的性能。
    cpu-max-prime选项指定了最大的素数为20000,如下: sysbench --test=cpu --cpu-max-prime=20000 run
    对于CPU的测试,我们要重点关注三个指标:上下文切换(context switch)、运行队列(run queue)和使用率 (utilization)。
    (1)上下文切换
    在操作系统中,若要将CPU切换到另一个进程,需要保存当前进程的状态并恢复另一个进程的状态:
    即将当前运行任务转为就绪(或者挂起、删除)状态,让另一个被选定的就绪任务成为当前任务。
    上下文切换包括保存当前任务的运行环境,恢复将要运行任务的运行环境等。
    过多的上下文切换会给系统造成很大的开销。
    (2)运行队列
    当Linux内核要寻找一个新的进程在CPU上运行时,需要考虑处于可运行状态的进程,运行队列容纳了系统中所有可运行的进程。
    理想情况下,调度器会让队列中的进程不断运行,如果CPU过载,就会出现调度器跟不上系统的情况,从而导致可运行的进程填满队列。
    队列越大,程序执行的时间就越长。
    “load”用于表示正在等待运行的队列长度,top命令可以让我们看到在一 分钟、5分钟和15分钟内CPU运行队列的大小。
    这个值越大则表明系统负荷越大。
    (3)使用率
    CPU使用率可分为以下几个部分。
    User Time:执行用户进程的时间占全部时间的百分比,通常是期望这个值越高越好。
    SystemTime:CPU内核运行及中断的时间占全部时间的百分比,通常是希望这个值越低越好,系统CPU占用率过高时,通 常表明系统的某部分存在瓶颈。
    Wait I/O:I/O等待的CPU时间占全部时间的百分比,如果I/O等待过高,那么说明系统中存在I/O瓶颈。
    Idle:CPU处于Idle状态的时间占全部时间的百分比。
    以下是一些很普遍的CPU性能要求,供大家参考。
    对于CPU的每一个核来说运行队列不要超过3,例如,如果是双核CPU就不要超过6。
    如果CPU正处于满负荷运行状态,那么使用率应该符合下列分布。 User Time:65%~70% SystemTime:30%~35% Idle:0%~5%
    对于上下文切换,要结合CPU使用率来看,如果CPU使用率满足上述分布,那么大量的上下文切换也是可以接受的。
    常用的监视上下文切换的工具有:vmstat、top、dstat和mpstat。
    通过禁用或启用CPU核,可以进行不同CPU核数的性能和压力测试。
    一般来说,对于数据库,比如MySQL,一条查询使用一颗CPU核,MySQL还不具备一个查询可以在多颗CPU核中并行运行的能力。
    数据库操作中如果有大量的内存读,比如读取索引、读取InnoDB buffer里的数据,那么往往会表现为CPU瓶颈,内存复制也是如此。

    9.1.3 内存测试
    使用sysbench测试内存的命令如下。 sysbench --test=memory --memory-block-size=8K --memory-total-size=4G run
    上述参数指定了本次测试的整个过程是在内存中传输4GB的数据量,每个块(block)的大小为8KB。

    9.1.4 I/O测试
    1.普通磁盘阵列测试
    (1)使用hdparm
    磁盘性能测试可采用hdparm命令,对于上线的服务器,为了简便,可用自带的命令hdparm初步判断磁盘的性能,确定工作是否正常。
    如果要更可靠地验证磁盘、RAID性能,建议使用专门的测试工具,如iozone或sysbench。
    hdparm的使用示例如下。
    如下命令可查看某SATA硬盘的设置。
    hdparm /dev/sda
    /dev/sda:
    IO_support = 0 (default 16-bit)
    readonly = 0 (off)
    readahead = 256 (on)
    geometry = 60801/255/63, sectors = 976773168, start = 0
    解释:
    geometry=60801【柱面数】/255【磁头数】/63【扇区数】,sectors=976773168【总扇区数】,start=0【起始扇区数】。
    如下命令可查看SSD的设置。
    hdparm /dev/sdc
    /dev/sdc:
    IO_support = 0 (default 16-bit)
    readonly = 0 (off)
    readahead = 256 (on)
    geometry = 36481/255/63, sectors = 586072368, start = 0
    以下命令用于检测硬盘的读取速率(buffered disk reads),需要多运行几次,以便更准确。
    hdparm -t /dev/sda
    /dev/sda:
    Timing buffered disk reads: 426 MB in 3.00 seconds = 141.82 MB/sec
    以下命令用于检测硬盘快取时的读取速率(cached reads),需要多运行几次,以便更准确。
    ahdparm -T /dev/sda
    /dev/sda:
    Timing cached reads: 22096 MB in 2.00 seconds = 11070.65 MB/sec
    其中的参数解释如下:
    -t:衡量顺序读取的能力,不经过操作系统缓存。
    -T:衡量系统的吞吐性能,未访问底层的物理设备,直接从操作系统缓存里读取数据。
    (2)使用dd
    通过dd命令可实现用指定大小的块复制一个文件,并在复制的同时进行指定的转换。
    dd命令的语法格式如下。 dd if=<source> of=<target> bs=<byte size> skip=<blocks> seek=<blocks> count=<blocks> conv=<conversion>
    以下仅以RHEL 5.4的dd为例来说明参数,其他平台所支持的参数可能不一样。
    if=<source>:指定源文件。默认为标准输入。
    of=<target>:指定目标文件。默认为标准输出。
    bs=<bytes>:同时设置读入/输出的块大小为bytes个字节。也可以指定其他单位,如KB、MB等。
    skip=<blocks>:从输入文件的开头跳过blocks个块后再开始复制。
    seek=<blocks>:从输出文件的开头跳过blocks个块后再开始复制。
    count=<blocks>:仅复制blocks个块。
    conv=<conversion>:用指定的参数转换文件,参数如下,可组合使用,中间用逗号分隔。
    ascii:转换ebcdic为ascii。
    ebcdic:转换ascii为ebcdic。
    ibm:转换ascii为alternate ebcdic。
    block:使每一行的长度都为cbs,不足部分用空格填充。
    unblock:使每一行的长度都为cbs,不足部分用空格填充。
    lcase:把大写字符转换为小写字符。
    ucase:把小写字符转换为大写字符。
    swab:交换输入的每对字节。
    noerror:如果发生错误,程序也将继续运行。
    notrunc:不截断输出文件。
    sync:填充每个块到指定字节,不足部分用空(NUL)字符补齐。
    dd命令还有一组参数oflag和iflag,用于控制源文件和目标文件的读写方式。
    iflag=flag[,flag]...
    oflag=flag[,flag]...
    标志(flag)可选的值如下。
    append:以追加(append)模式写数据。这个标志仅适用于输出(写文件)。如果和of=file联合使用,则需要同时设置conv=notrunc。
    dsync:采用同步I/O读写数据,确保数据刷新到了磁盘。
    sync:与上者类似,但同时也对元数据生效,在测试数据库机器的磁盘性能时,为了得到更真实的性能数据,建议使用 sync或dsync的方式读写数据。
    direct:使用direct I/O操作数据,可以避免操作系统缓存的影响,即读或写文件时越过操作系统的读写缓存。
    如果指定 oflag=direct,则写文件时会忽略缓存的影响;而如果指定iflag=direct,则读文件时会忽略缓存的影响。
    fullblock:为输入积累完整块(仅针对iflag)。
    nonblock:采用非阻塞I/O模式。
    nofollow:不跟随链接文件,即忽略链接文件指向的文件。当从标准输入读取或写入到标准输出时,不要使用此选项。
    noctty:不根据文件的指派控制终端。
    例1: 测试磁盘写能力,利用操作系统写缓存。
    dd if=/dev/zero of=blah.out bs=1M count=2000
    或者: time (dd if=/dev/zero of=blah.out bs=1M count=2000 ; sync )
    因为/dev/zero是一个伪设备,它只会产生空字符流,对它不会产生I/O,所以,I/O都集中在of文件中,of文件只用于写,所以这个命令相当于测试磁盘的写能力。
    dd默认的方式不包括“同步(sync)”命令。
    也就是说,dd命令完成之前并没有让系统真正把文件写到磁盘上。
    脏数据可能还在操作系统的缓存里,并没有刷新到磁盘上。
    如果内存比较大,我们往往可以看到磁盘的写能力很高。
    如果以上命令在一块普通sata硬盘上执行,结果如下,可以看到,每秒写入828MB,显然磁盘的写能力远没有这么高。
    dd if=/dev/zero of=blah.out bs=1M count=2000
    2000+0 records in
    2000+0 records out
    2097152000 bytes (2.1 GB) copied, 2.53394 seconds, 828 MB/s
    我们可以更改系统参数,把可用内存降低到很小,或者使用参数oflag=sync来确保已将数据刷新到了磁盘。
    例2: 使用oflag=sync模式测试磁盘写能力,对于数据库机器,一般建议这样测试磁盘。
    time dd if=/dev/zero of=blah.out oflag=sync bs=1M count=2000
    对比例1的测试结果,本次测试的写入速度大大降低,这才是比较真实的写入速度。
    time dd if=/dev/zero of=blah.out oflag=sync bs=1M count=2000
    2000+0 records in
    2000+0 records out
    2097152000 bytes (2.1 GB) copied, 27.861 seconds, 75.3 MB/s
    real 0m27.913s
    user 0m0.003s
    sys 0m3.204s
    一般来说,随着bs值的增加,吞吐往往会更高。
    例3: 测试磁盘读能力。
    time dd if=/dev/sdb1 of=/dev/null bs=8k
    因为/dev/sdb1是一个物理分区,对它的读取会产生I/O,而/dev/null是伪设备,相当于黑洞,of到该设备不会产生I/O,
    所以, 这个命令的I/O只发生在/dev/sdb1上,也相当于测试磁盘的读能力。
    例4: 测试同时读写的能力。
    time dd if=/dev/sdb1 of=test1.dbf bs=8k
    这个命令下,一个是物理分区,一个是实际的文件,对它们的读写都会产生I/O(对/dev/sdb1是读,对test1.dbf是写),
    假设它们都在一个磁盘中,这个命令就相当于测试磁盘同时读写的能力。
    可以另开一个会话(session),运行命令“kill -s USR1 pid”,用于显示dd进程的I/O统计,pid为正在执行dd命令的进程id,命令如下。
    $ dd if=/dev/zero of=/dev/null & pid=$!
    $ kill -USR1 $pid; sleep 1; kill $pid

    2.SSD测试
    对于SSD,也可以使用dd进行测试和验证,但对于数据库负载,为了更好地模拟负荷,建议使用更智能的工具进行测试, 如sysbench,sysbench的具体使用方法,请参考9.2.2节。
    如下是一些SSD的测试建议:
    测试要尽可能避免缓存(cache)的影响。
    任何磁盘产品,在碰到I/O瓶颈的时候,都不可能会很快,这个时候才是真正的磁盘的性能。
    如果我们在测试一些数据库产品的时候,发现有非常高的吞吐率,那么就要思考一下,是不是有什么其他因素影响了测试结果,
    网上的很多测评就是陷入了这样一个误区,忽略了缓存的影响,这是一个致命的错误。
    要注意碎片、空间占用的影响。
    随着使用时间的增长,SSD可能有碎片,空间占用率也可能上升,这个时候性能就可能会下降。
    一般来说,针对SSD的测试需要较长时间,因为可能有垃圾回收(Garbage Collection,GC)机制的影响,需要将其考虑进去,笔者个人偏向于每种测试模型的测试时长均大于1小时。
    而且,你需要测试不同空间占用比下的性能,现实中,一般如果数据库占用了90%以上的磁盘空间,则必须要考虑扩容,
    所以对于企业级应用,可以测试一下几乎写满(>90%)情况下的性能,此时的性能更有参考价值。
    RAID卡、I/O控制器、缓存等因素也会影响到SSD的性能。需要留意这一点,高端RAID卡和中低端RAID卡的性能有很大的差别。
    可测试单盘性能,如果需要做RAID,那么可测试一下RAID5和RAID1+0。
    出于节省成本和空间的考虑,有些人使用RAID5。虽然理论上RAID5的性能会比较差,但RAID卡厂商一般专门提供了优化RAID5的技术,而且很多情况下I/O也不再成为瓶颈了。
    如果单盘空间足够大且成本合适的话,那么不做RAID,直接测试单盘性能也是可以的。
    不仅要测试吞吐率,还需要测试响应的稳定性,以反映真实的环境。
    验证案例是否覆盖了所有的情况,而且要使用成熟稳定的工具来完成,以免破坏数据。
    SSD对于温度会比较敏感,需要留意温度的影响。

    9.1.5 网络测试
    一般网卡出故障的可能性非常低,所以我们可以不用过多地进行验证测试,在系统部署后验证即可,
    可用ethtool命令验证网卡,也可以使用专门的网络评测工具进行验证,
    还可以通过网络传输文件来验证,比如,直接ftp一个大文件到ftp服务器以验证网络传输是否正常。

    9.2 MySQL测试
    9.2.1 概述
    MySQL测试的范围很广,我们出于不同的目的进行测试,最常见的是性能基准测试。
    有时还需要做一些其他测试,比如,验证MySQL的复制特性,在高并发的压力下,不断破坏从库(模拟宕机、磁盘空间满等情况),来查看复制能否顺利进行。
    比如,通过测试宕机下的灾难恢复性,来衡量灾难恢复所需要的时间等。
    本节将仅叙述MySQL的性能测试。
    影响性能测试的因素较多,除了MySQL自身之外,文件系统、操作系统块大小、应用访问模式、RAID阵列条带大小等诸多因素都对性能有或多或少的影响。
    本章不会对所有类型都进行测试,但会说明测试的方法及注意事项,读者可以按照自己拟定的方法和步骤测试验证不同软硬件设置下的MySQL性能。

    9.2.2 常用测试工具的介绍和使用
    MySQL的测试工具,推荐用sysbench。
    虽然hammerora、super-mark、tpc-c等一些其他工具也很强大,
    但sysbench的文件I/O测试与InnoDB的行为很相似,针对MySQL也有比较完善的测试模型,还可以方便地修改lua脚本,以实现更强大、更灵活的测试功能。
    其实,设计sysbench的初衷就是为了衡量MySQL的性能,而很多其他工具,对于MySQL的支持往往只是一个选项,功能还不够强大,难以模拟真实的数据库负荷。
    MySQL自带的mysqlslap也是一个不错的工具,它是从5.1.4版开始的一个MySQL官方提供的压力测试工具,可通过模拟多个并发客户端访问MySQL来执行压力测试。
    这两个工具可以满足大部分情况下的性能测试和压力测试。
    sysbench可以自定义lua脚本,开发人员可以编写适合自己业务逻辑的lua脚本。
    当然也可以使用其他高级语言编写测试工具,这样会更灵活,更接近实际业务数据库操作。
    1.sysbench的使用
    目前sysbench主要支持MySQL、PostgreSQL、Oracle这3种数据库。
    它主要包括以下几种方式的测试。
    Fileio:文件I/O测试。
    Cpu:CPU性能测试。
    Memory:内存性能测试。
    Threads:线程性能测试。
    Mutex:Mutex性能测试。
    Oltp:OLTP测试,MySQL一般会选择此种测试类型。
    (1)安装
    首先,从https://github.com/akopytov/sysbench下载源码包,单击Download Zip。然后,按照如下步骤进行安装。
    unzip sysbench-0.5.zip
    cd sysbench-0.5
    ./autogen.sh
    ./configure --with-mysql-includes=/usr/local/mysql/include --with-mysql-libs=/usr/local/mysql/lib
    make
    make install
    用如上的参数进行编译的话,需要确保你的MySQL lib目录下有对应的库文件,如果没有,则可以下载devel或share包来进行安装。
    也可以下载MySQL的二进制安装包解压到/usr/local/mysql下。
    (2)开始测试
    在sysbench--test=memory命令后添加help可以查看帮助。
    sysbench --test=memory help
    一些参数解析如下:
    --percentile 95%:响应时间,也就是删除5%的响应时间最长的请求,然后从剩余的请求中选取最大的响应时间值。
    --max-time:运行时间限制,单位是秒。
    --num-threads:线程数。
    --max-requests:查询数限制。
    下面来举例说明。
    1)CPU性能测试。
    sysbench --test=cpu --cpu-max-prime=20000 run
    CPU测试主要是进行素数的运算,在上面的例子中,指定了最大的素数为20000,也可以根据机器CPU的性能来适当调整数值。
    如下命令,执行20s就输出了,而不会等待命令执行完。
    sysbench --test=cpu --cpu-max-prime=20000 run --max-time=20
    2)线程测试。
    sysbench --test=threads --num-threads=64 --thread-yields=1000 --thread-locks=8 run
    3)磁盘I/O性能测试。
    sysbench --test=fileio --num-threads=16 --file-total-size=12G --file-test-mode=rndrw prepare
    sysbench --test=fileio --num-threads=16 --file-total-size=12G --file-test-mode=rndrw run
    sysbench --test=fileio --num-threads=16 --file-total-size=12G --file-test-mode=rndrw cleanup
    上述代码分为3个步骤,第一条命令初始化文件,第二条命令执行测试,第三条命令清理文件。
    --num-threads参数指定了最大创建16个线程,
    --file-total-size参数指定创建文档的总大小为12GB,
    --file-test-mode指定文档的读写模式为随机读写。
    磁盘I/O性能测试是进行数据库基准测试时要着重加以研究的。
    我们需要衡量各种因素,比如操作类型、读写的频率、I/O大小、是随机读写还是顺序读写、写的类型是异步还是同步、并发线程情况、操作系统缓存状态及文件系统有哪些调优等因素。
    文件测试类型(file-test-mode)有如下几种。
    seqwr:顺序写。
    seqrewr:顺序重写(rewrite)。
    seqrd:顺序读。
    rndrd:随机读。
    rndwr:随机写。
    rndrw:随机读写。
    4)内存测试。
    sysbench --test=memory --memory-block-size=8K --memory-total-size=4G run
    上述参数指定了本次测试的整个过程是在内存中传输4GB的数据量,每个块(block)的大小为8KB。
    5)OLTP测试。
    在测试之前请预先创建数据库,并给予测试用户足够的权限。
    mysql > create database sbtest;
    mysql > grant all privileges on sbtest.* to test@’ localhost’ identified by ‘ test’ ;
    如下例子演示了多线程如何测试MySQL。
    首先初始化数据。
    sysbench --test=./sysbench/tests/db/oltp.lua --mysql-table-engine=innodb --oltp-tables-count=256 --oltp-table-size=1000000 --mysql-user=test --mysql- password=test --mysql-socket=/tmp/mysql.sock prepare
    上述参数指定了本次测试的表存储引擎类型为InnoDB,指定了表的最大记录数为1000000,初始化生成256个表。
    测试OLTP时,可以自己先创建数据库sbtest,或者自己用参数--mysql-db来指定其他数据库。
    然后进行实际测试,测试模型是OLTP,并发8个线程,执行1个小时,如下:
    sysbench --test=./sysbench/tests/db/oltp.lua --oltp-tables-count=256 --oltp-table-size=1000000 --mysql-user=test --mysql-password=test --mysql- socket=/tmp/mysql.sock --max-time=3600 --max-requests=0 --num-threads=8 --report-interval=10 run
    其中,--report-interval=10表示每10s就输出一次数据,输出格式类似如下。
    [ 10s] threads: 2, tps: 290.39, reads: 4065.82, writes: 1161.58, response time: 8.65ms (95%), errors: 0.00, reconnects: 0.00
    [ 20s] threads: 2, tps: 270.90, reads: 3795.10, writes: 1083.80, response time: 10.14ms (95%), errors: 0.00, reconnects: 0.00
    [ 30s] threads: 2, tps: 277.40, reads: 3883.50, writes: 1109.40, response time: 9.82ms (95%), errors: 0.00, reconnects: 0.00
    [ 40s] threads: 2, tps: 273.50, reads: 3828.09, writes: 1094.00, response time: 9.93ms (95%), errors: 0.00, reconnects: 0.00
    测试完成后,清理数据。
    sysbench --test=./sysbench/tests/db/oltp.lua --oltp-tables-count=256 --oltp-table-size=1000000 --mysql-user=test --mysql-password=test --mysql- socket=/tmp/mysql.sock cleanup

    2.mysqlslap的使用
    mysqlslap是MySQL 5.1.4及以后版本自带的一个用于实现负载性能测试和压力测试的工具。
    它可以模拟多个客户端对数据库进行施压,并生成报告以衡量数据库的一些指标。
    其工作原理可分为如下三个步骤。
    1)首先生成测试数据,即创建表,导入数据。这个步骤将使用单个客户端连接执行。
    2)然后运行性能测试,可以使用单线程或多线程。
    3)最后清理测试数据。这个步骤将使用单个客户端连接执行。
    一些使用示例如下所示。参数的具体说明请参考官方文档。
    1)分别并发10个线程或100个线程进行混合测试。
    mysqlslap --uroot --engine=innodb --auto-generate-sql
    --auto-generate-sql-unique-query-number=100 --auto-generate-sql-unique-write-number=100 --auto-generate- sql-write-number=1000
    --create-schema=test --auto-generate-sql-load-type=mixed --concurrency=10,100 --number-of-queries=1000 --iterations=1
    --number-char- cols=1 --number-int-cols=8 --auto-generate-sql-secondary-indexes=1 --debug-info --verbose
    以上命令的大致步骤是,首先生成1000条数据(--number-of-queries=1000),
    然后进行混合测试(--auto-generate-sql-load-type=mixed,SELECT操作和INSERT操作大致各占一半),此时数据会不断增长。
    然后,先使用10个并发线程进行测试,再用100个并发线程进行测试(--concurrency=10,100),进行新的并发测试前会清理和初始化测试数据。
    需要留意的是,自动生成的SELECT语句是全表扫描,语句如下。
    SELECT intcol1,intcol2,intcol3,intcol4,intcol5,intcol6,intcol7,intcol8,charcol1 FROM t1
    INSERT语句类似如下。
    INSERT INTO t1 VALUES (uuid(),389111603,476395693,1231278962,1952007439,1880139043,1004384052,914532...
    2)测试基于主键查找的性能。
    time mysqlslap -uroot --engine=innodb --auto-generate-sql-load-type=key
    --auto-generate-sql --auto-generate-sql-write-number=100000 --auto-generate-sql-guid- primary
    --number-char-cols=10 --number-int-cols=10 --concurrency=10,100 --number-of-queries=5000
    以上命令的大致步骤是,首先创建一个表,使用单线程初始化插入100000条记录,然后并发10条线程执行基于主键的查询。
    接着删除库表,再初始化插入 100000条记录,然后并发100条线程执行基于主键的查询。
    基于主键的查询可能被缓存,所以有必要生成不同的SELECT语句。
    3)生成一张两千万条记录的表,进行混合型负荷测试(SELECT+INSERT),语句如下。
    mysqlslap -uroot -p --engine=innodb --auto-generate-sql --auto-generate-sql-write-number=20000000
    --auto-generate-sql-add-autoincrement --auto-generate-sql- secondary-indexes=2 --concurrency=50 --number-of-queries=1000000 --number-char-cols=3 --number-int-cols=2 --debug-info
    以上命令的大致步骤是,初始化记录时使用自增主键(--auto-generate-sql-add-autoincrement)并发50个线程进行查询,一共执行100万个查询,
    也就是说平均每个线程大概执行2万个查询,如果有自增ID,那么SELECT语句是基于自增ID的,这样更能反映生产环境实际情况。
    对于如上的命令,一台普通的数据库服务器(SAS硬盘三块:SAS 15K 300G*3,做成了RAID5),
    初始化过程中大概会插入2000万条记录,到达1500万条记录的时候,INSERT速率大概可以达到6000~7000条记录每秒。
    iostat命令显示每秒写入20MB~30MB的数据。
    插入2000万条记录,初始化完成后,开始并发50条线程进行混合测试,同时有INSERT和SELECT操作。
    大概每秒执行INSERT操作600次,SELECT操作500次。

    9.2.3 MySQL基准测试模型
    1.指引
    基准测试的目的之一是在平时做好数据准备,记录标准的数据库软硬件配置下的性能数据,以便在未来更改数据库配置或调整升级数据库主机时有一个参照。
    很多人在新机器上线后不想做基准测试,认为基准测试繁琐、耗时,而且难以度量。
    如果不是标准化的采购、安装、部署,就很难说主机配置得完全正确,所以,如果有一个工具可以预先针对CPU、磁盘、网络、数据库进行压力测试,验证硬件是否已经正确配置,就省事多了。
    我们还可以把基准测试的历史数据记录下来,在以后进行选购或升级软硬件的时候,再重新进行基准测试,从而验证软硬件的升级效果。
    基准测试的一个重要环节就是基准测试模型,我们需要一个相对简单、高效,实现起来成本比较低的模型。
    想用测试模型来真实反映现实的生产环境是很难做到的,
    但是我们可以按照数据库的理论和实践,设置一些比较能够反映生产负荷的输入条件,评估测试的输出指标,从而建立可以用来衡量数据库架构、软硬件配置的基准模型。
    以下将介绍下具体的思路和设计方法。
    当我们选择硬件的时候,需要考虑到各项成本,对于项目风险、开发成本和维护成本比较难以衡量,而计算机性能相对来说是更好地限定和比较的,所以可以考虑建立一个MySQL的基准测试模型。
    性能测试很难模拟真实环境的负荷,一般使用比较简单的模型,因为真实环境下的负荷具有不确定、变化较大、复杂且难以理解等特点,故而难以得出结论,不容易对比。
    单个产品的基准测试,主要用于对比版本和衡量软硬件调整的效果,对于整个应用系统的测试没有太大的参考意义,应用系统自己的基准测试模型会比单个 MySQL测试模型更全面更准确。
    明确目标后,再进行基准测试,才能更好地选择工具和测试方法。
    如果是SSD,建议文件的最大空间不超过磁盘空间的85%,以避免SSD空间占比可能带来的性能下降。
    除了关注吞吐率(TPS),还需要关注响应时间(responsetime)。
    需要留意并发性(concurrency),如MySQL Server同时运行的线程数(threads_running)和伸缩性(scalability)等。
    假如我们增加了一倍线程,那么好的伸缩性就意味着系统的吞吐也可以线性地增加一倍,或者说当我们增加了一倍的硬件资源,那么系统的吞吐也可以翻倍。
    基准测试需运行足够长的时间。关于数据预热所需要的时间,一般查看吞吐量的曲线图就可以大致判断出来,很多情况下,可能需要运行半个小时以上才会稳定下来。
    尽量确保测试结果在同样的配置下可以重现。
    衡量MySQL性能需要考虑诸多因素,包括但不限于以下这些因素。
    硬件:CPU速度、CPU架构、CPU个数、CPU核数、总线速度、内存访问速度、设备I/O性能、RAID卡、磁盘条带、块大小、网络设备。
    操作系统:原生API性能、线程、锁、内存、I/O调度算法。
    客户端连接次数。
    数据库服务器处理任务的线程个数。
    数据库设计。
    数据量。
    应用类型。
    数据访问模式:一般来说我们的应用热点数据较小,读远大于写。如果你的应用热点数据比较大,访问各种数据比较分散,分布比较均匀,那么这种测试更考验了数据库的原始性能。
    数据库版本:社区版、企业版还是第三方分支版本。
    引擎。
    数据库配置。比如NUMA策略、页块大小(pagesize)、是独立表空间还是共享表空间、顺序访问和随机访问文件的分布、InnoDB buffer pool的大小及其他一 些影响重大的参数。
    重要的参数修改,每次尽可能少更改点参数,一次更改太多的参数不容易判断问题的所在。
    2.模型简介
    以下是一个测试MySQL数据库的简单模型。
    ## MySQL基准测试模型介绍。
    ## 组合以下不同条件 :测试类型、线程数、表个数、表记录数 (大小 ) 进行测试
    ## ================开始测试 =======================
    ## 测试逻辑 :对每种测试类型、对各种并发线程数、对指定的表个数、对不同表大小
    ## prepare
    ## sysbench 测试 ,默认测试 1200s
    ## cleanup
    ## ====================结束测试 ========================
    测试类型一般选择oltp。对于单个表,将按顺序执行如下操作。
    1)几个基于主键的查询。
    2)主键范围查找。
    3)主键范围查找+聚合函数。
    4)主键范围查找+文件排序。
    5)主键范围查找+临时表+文件排序。
    6)更新操作(基于主键查询)。
    7)删除操作(基于主键查询)。
    8)插入操作。
    9)提交。
    由于sysbench官方版本的oltp模型里没有复杂的查询连接(JOIN)操作,但两三个表的连接又是比较普遍的,因此可以考虑更改下官方的oltp测试模型,以反映真 实的生产负荷。
    3.测试脚本示例
    如下是一个按照上面的模型编写出的脚本示例,这里将叙述它所实现的功能,以及分析几个测试脚本的输出结果。
    测试脚本的代码请到www.db1110.com上下载。
    测试脚本可实现如下功能:
    1)收集操作系统、硬件信息和MySQL脚本信息。
    如下是收集到的一些信息。
    =========================Host==============================
    Hostname | xxxx
    Release | Red Hat Enterprise Linux Server release 5.4 (Tikanga)
    Processors | physical = 2, cores = 8, virtual = 16, hyperthreading = yes
    Models | 16xIntel(R) Xeon(R) CPU E5520 @ 2.27GHz
    Total | 15.6G
    # RAID Controller ############################################
    Controller | No RAID controller detected
    # Disk Schedulers And Queue Size #############################
    sda | [cfq] 128
    sdb | [cfq] 128
    ============================MySQL===========================
    # Report On Port 3306 ########################################
    User | root@localhost
    Hostname | xxxxxx
    Version | 5.1.58-log MySQL Community Server (GPL)
    Built On | unknown-linux-gnu x86_64
    Databases | 5
    # Table cache ################################################
    Size | 4096
    # InnoDB #####################################################
    Version | default
    Buffer Pool Size | 2.5G
    File Per Table | OFF
    Page Size | 16k
    Log File Size | 2 * 360.0M = 720.0M
    Flush Log At Commit | 2
    Thread Concurrency | 16
    Txn Isolation Level | READ-COMMITTED
    sync_binlog | 20
    innodb_max_dirty_pages_pct = 50
    2)可以在脚本中调整MySQL的参数设置。
    3)收集操作系统的性能信息,在测试期间的内存、CPU、磁盘等各种信息都应该收集起来,不管目前有没有用,收集尽可能多的信息会方便自己以后的分析。
    4)能使用sysbench的oltp模型进行测试,并且能够生成图形。
    以下是性能测试脚本的运行结果,我们将对这些测试完成后生成的图形做一些分析。
    例1: 图9-1是不同线程(thread)数量的时候,事务吞吐率(tps)的变化图,数据小于InnoDB缓冲池(0.7382*buffer)。
    图9-1中所示的MySQL实例有256张表,每张表有3万记录,数据小于InnoDB缓冲区。
    随着线程数量的增加,事务吞吐率会缓慢下降,这说明等待的时间在增长, 从而导致事务吞吐率下降。
    对于线程数量不断增加的数据库测试,性能吞吐率曲线最开始往往是线性增长的,但终将到达一个拐点,可能到达拐点的时候,是因为某项资源出现了瓶颈, 对资源的竞争将开始影响到性能。
    比如图9-1的压力测试中,随着线程数量的增加,吞吐率也在增加,但如果存在过多的线程,由于CPU资源不够,将导致频繁的上下文切换,从而导致延时增加。
    如果是CPU资源的瓶颈,那么性能下降得不是很快;但如果是内存瓶颈,则属于另外一种情况,性能可能会急剧变差;磁盘I/O瓶颈同样可能导致急剧的性能变差,请参见下面例2的图。
    例2: 图9-2和图9-1类似,描述了不同线程数下事务吞吐率的变化,不过数据占用空间远远大于InnoDB缓冲池(4.8573*buffer)。可以看到事务吞吐率已经大大下降了。
    例3: 图9-3描述了不同数据量下,事务吞吐率的变化。在8个线程、256张表的情况下,随着数据量的增长,事务吞吐率逐渐下降。
    随着数据的不断增长,3万记录也逐渐增长到5万、10万、20、30万,事务吞吐率则从1500tps下降到了400tps。
    由此可以证明,热点数据能否缓存在内存中,对事务的吞吐率影响是很大的。
    例4: 图9-4由多个子图构成,分别展示了事务吞吐、读、写、响应时间随时间变化的曲线。数据库实例的数据空间占用小于InnoDB缓冲(0.7382*buffer)。
    对于我们来说,更有效的数据是性能趋于稳定后的数据,大家做测试的时候,一定要确认自己是否已经运行了足够长时间,可以简单地通过查看事务吞吐率是否趋于稳定来衡量时间的长短。
    例5: 图9-5说明了磁盘的I/O瓶颈可能会导致性能急剧变差。
    可以看到在数据远大于InnoDB缓冲(4.8573*buffer)的时候,事务吞吐率下降了很多。
    且随着时间的增长,有时会突然出现性能急剧下降的情况(见图9-5中长 的“毛刺”)。
    这主要是MySQL刷新数据的机制不够完善所导致的。
    高并发读写的数据库负载很可能会出现此种情况,且MySQL 5.1很难避免出现这种情况。
    必须承认 这是一个固有的缺陷,需要想办法尽可能地避免。
    MySQL 5.6对此有一定的改善。

    4.基准测试的不足及注意事项
    不容易测试系统的其他特性:稳定性、安全性、扩展性、可用性、灾难恢复性等。
    没有计算成本(磁盘、内存等),但即使计算了成本,也可能会被厂商欺骗,厂商会使用最优的配置,以尽可能低的成本支撑更大的吞吐。
    没有衡量能源消耗。
    没有考虑到复杂的网络环境。
    用户考虑的是这个产品能够满足何种服务品质协议(service-levelagreement),比如说99.99%的时间是可用的,而基准测试更多考虑的是能够达到的平均分数。
    一般测试报告列出的可能是80%~90%的系统资源使用率下的数据,没有考虑系统资源严重瓶颈,而现实中往往并非如此,
    在系统资源出现严重瓶颈时,性能、安全性、稳定性可能急剧下降。
    一般来说,新版本的功能更强,优化器更复杂,更擅长处理复杂的查询。在高并发和大数据集下会更具备优势。
    可能很难模拟复杂的实际访问。
    针对不同问题设计负荷,比如,是模拟计算密集型(CPU-bound)的负荷还是I/O密集型(I/O-bound)的负荷呢?
    向上扩展(scale-up)可以提高吞吐,但存在一个最佳配置,超过这个配置后,吞吐不会再有明显增加。
    即使增加了CPU、增大了内存,增加了更快速的硬盘,往往还是得不到更高的性能,瓶颈点在于数据库自身的等待而不是硬件,
    MySQL数据库难以充分利用硬件资源,所以生产环境更倾向于多实例部署,倾向于不那么强劲的服务器主机。
    研发、测试人员往往不擅长做数据库的压力测试,可能存在的问题包括不熟悉硬件,
    测试时MySQL Server的参数并没有经过优化,没有使用足够多的真实可靠的数据,没有运行足够长时间的测试计划以预热数据等。
    如果可能,应该提供生产环境的真实数据供研发、测试人员测试,可以考虑的一个方法是重放日志来模拟负载,但必须也要模拟多线程并发的场景。
    生产环境数据库和Web服务器一般分布在不同的主机上,严格来说,测试工具部署在非数据库机器上更好,但是,测试工具、客户端和数据库在同一台机器上 做测试一般也是可行的。

    9.3 应用数据库性能测试
    数据库的性能测试可能是由其他团队来实施,而不是由DBA来完成的,由于关注的重心不一样,使用的工具不一样,可能分析的结果也会有偏差,
    但只要我们了解了测试的本质,熟悉了数据库,就可以阅读其他部门和团队所做的数据库测试报告,从而得出自己认可的结果。
    一般研发、测试人员可能会专门使用一些Web测试工具,如Apache自带的工具ab,包括http_load、Webbench、Siege、JMeter等。
    这些工具会调用一些Web页面程 序,对数据库间接进行施压,如果选择的测试模型和步骤合适,往往比直接使用工具对数据库进行压力测试更合理。
    应用负载往往是复杂的,很难去模拟,即使是企业级的测试工具也难以重现生产环境,
    有兴趣的读者可以去试用一下tcpcopy这个工具,它可以把生产环境的流量复制到测试环境中,对于测试数据库的性能很有帮助,尤其是测试只读的MySQL从库。

    小结:
    本章介绍了MySQL的一个基准测试模型,比较简单,大家可以在上面加入自己的想法。
    随着读者MySQL水平的提高,会逐渐意识到性能测试的重要性。
    如果需要提高自身的软硬件架构功力,就一定要多做性能测试,通过性能测试,可以对数据架构有更深刻的理解。
    由于数据库性能测试很耗时、繁琐,因此尽可能使用自动化测试。
    数据库性能测试的方法和结果也应该分享给其他团队,让他们把握当下软硬件的能力和极限,减少沟通成本,避免错误决策。

  • 相关阅读:
    linux 短信收发
    sama5d3 环境检测 adc测试
    【Codeforces 723C】Polycarp at the Radio 贪心
    【Codeforces 723B】Text Document Analysis 模拟
    【USACO 2.2】Preface Numbering (找规律)
    【Codeforces 722C】Destroying Array (数据结构、set)
    【USACO 2.1】Hamming Codes
    【USACO 2.1】Healthy Holsteins
    【USACO 2.1】Sorting A Three-Valued Sequence
    【USACO 2.1】Ordered Fractions
  • 原文地址:https://www.cnblogs.com/BradMiller/p/12036112.html
Copyright © 2011-2022 走看看