Mysql数据库测试工具——sysbench

sysbench安装

# yum -y install make automake libtool pkgconfig libaio-devel openssl-devel mysql-devel
# cd /usr/src/
# wget https://github.com/akopytov/sysbench/archive/refs/tags/1.0.20.tar.gz
# tar xvf 1.0.20.tar.gz
# cd sysbench-1.0.20/
# ./autogen.sh
# ./configure
# make -j
# make install

这些命令是在Linux系统上安装sysbench基准测试工具的步骤。

  1. yum -y install make automake libtool pkgconfig libaio-devel openssl-devel mysql-devel: 这个命令使用yum包管理器安装了一些必要的依赖项,包括make、automake、libtool、pkgconfig、libaio-devel、openssl-devel和mysql-devel。这些依赖项是编译和安装sysbench所需的工具和库。
  2. cd /usr/src/: 这个命令将当前工作目录更改为/usr/src/,通常用于存放源代码文件。
  3. wget https://github.com/akopytov/sysbench/archive/refs/tags/1.0.20.tar.gz: 这个命令使用wget工具下载sysbench的源代码压缩包。下载的文件名为1.0.20.tar.gz,它是sysbench 1.0.20版本的源代码。
  4. tar xvf 1.0.20.tar.gz: 这个命令解压缩下载的源代码压缩包。tar命令用于解压缩和归档文件,xvf参数表示解压缩和显示详细信息。
  5. cd sysbench-1.0.20/: 这个命令将当前工作目录更改为解压缩后的sysbench源代码目录。
  6. ./autogen.sh: 这个命令运行autogen.sh脚本,用于生成configure脚本。autogen.sh脚本负责检查系统环境并生成配置脚本,以便后续的编译和安装过程。
  7. ./configure: 这个命令运行configure脚本,用于配置sysbench的编译选项和依赖项。configure脚本会检查系统环境和依赖项,并生成Makefile文件,以便后续的编译过程。
  8. make -j: 这个命令运行make工具来编译sysbench。-j参数表示并行编译,加快编译速度。
  9. make install: 这个命令运行make工具来安装已编译的sysbench。make工具会将编译生成的可执行文件和其他必要的文件复制到系统指定的位置,以便在任何地方都可以使用sysbench命令。

安装完成后,压测脚本默认会安装在 /usr/local/share/sysbench 目录下。

我们看看该目录的内容。

除了oltp_common.lua是个公共模块,其它每个 lua 脚本都对应一个测试场景。

sysbench用法讲解

sysbench 命令语法如下:

sysbench [options]... [testname] [command]

命令中的testname是测试项名称。sysbench 支持的测试项包括:

*.lua:数据库性能基准测试。

fileio:磁盘 IO 基准测试。

cpu:CPU 性能基准测试。

memory:内存访问基准测试。

threads:基于线程的调度程序基准测试。

mutex:POSIX 互斥量基准测试。

command是 sysbench 要执行的命令,支持的选项有:prepare,prewarm,run,cleanup,help。注意,不是所有的测试项都支持这些选项。

options是配置项。sysbench 中的配置项主要包括以下两部分:

1. 通用配置项。这部分配置项可通过 sysbench --help 查看。例如,

# sysbench --help
...
General options:
  --threads=N                     number of threads to use [1]
  --events=N                      limit for total number of events [0]
  --time=N                        limit for total execution time in seconds [10]
 ...

2. 测试项相关的配置项。各个测试项支持的配置项可通过 sysbench testname help 查看。例如,

# sysbench memory help
sysbench 1.0.20 (using bundled LuaJIT 2.1.0-beta2)

memory options:
  --memory-block-size=SIZE    size of memory block for test [1K]
  --memory-total-size=SIZE    total size of data to transfer [100G]
  --memory-scope=STRING       memory access scope {global,local} [global]
  --memory-hugetlb[=on|off]   allocate memory from HugeTLB pool [off]
  --memory-oper=STRING        type of memory operations {read, write, none} [write]
  --memory-access-mode=STRING memory access mode {seq,rnd} [seq]

对 MySQL 进行基准测试的基本步骤

下面以oltp_read_write为例,看看使用 sysbench 对 MySQL 进行基准测试的四个标准步骤:

prepare

生成压测数据。默认情况下,sysbench 是通过 INSERT INTO 命令来导入测试数据的。如果是使用 LOAD DATA LOCAL INFILE 命令来导入,sysbench 导数速度能提升30%,具体可参考:使用 LOAD DATA LOCAL INFILE,sysbench 导数速度提升30%

# sysbench oltp_read_write --mysql-host=10.0.0.64 --mysql-port=3306 --mysql-user=admin --mysql-password=Py@123456 --mysql-db=sbtest --tables=30 --table-size=1000000 --threads=30 prepare

命令中各个选项的具体含义如下:

  • oltp_read_write:测试项,对应的是/usr/local/share/sysbench/oltp_read_write.lua。这里也可指定脚本的绝对路径名。
  • --mysql-host、--mysql-port、--mysql-user、--mysql-password:分别代表 MySQL 实例的主机名、端口、用户名和密码。
  • --mysql-db:库名。不指定则默认为sbtest。
  • --tables :表的数量,默认为 1。
  • --table-size :单表的大小,默认为 10000。
  • --threads :并发线程数,默认为 1。注意,导入时,单表只能使用一个线程。
  • prepare:执行准备工作。

oltp_read_write 用来压测 OLTP 场景。在 sysbench 1.0 之前, 该场景是通过 oltp.lua 这个脚本来测试的。不过该脚本在 sysbench 1.0 之后就被废弃了,但为了跟之前的版本兼容,该脚本放到了/usr/local/share/sysbench/tests/include/oltp_legacy/ 目录下。

鉴于 oltp_read_write.lua 和 oltp.lua 两者的压测内容完全一致。从 sysbench 1.0 开始,压测 OLTP 场景建议直接使用 oltp_read_write。

prewarm(可省略)

预热。主要是将磁盘中的数据加载到内存中。

# sysbench oltp_read_write --mysql-host=10.0.0.64 --mysql-port=3306 --mysql-user=admin --mysql-password=Py@123456 --mysql-db=sbtest --tables=30 --table-size=1000000 --threads=30 prewarm

除了需要将命令设置为 prewarm,其它配置与 prepare 中一样。

run

压测。

# sysbench oltp_read_write --mysql-host=10.0.0.64 --mysql-port=3306 --mysql-user=admin --mysql-password=Py@123456 --mysql-db=sbtest --tables=30 --table-size=1000000 --threads=64 --time=60 --report-interval=10 run

其中,

  • --time :压测时间。不指定则默认为 10 秒。除了 --time,也可通过 --events 限制需要执行的 event 的数量。
  • --report-interval=10 :每 10 秒输出一次测试结果,默认为 0,不输出。

cleanup

清理数据。

# sysbench oltp_read_write --mysql-host=10.0.0.64 --mysql-port=3306 --mysql-user=admin --mysql-password=Py@123456 --mysql-db=sbtest --tables=30 cleanup

这里只需指定 --tables ,sysbench 会串行执行 DROP TABLE IF EXISTS sbtest 操作。

 

如何分析 MySQL 基准测试结果

下面我们分析下 oltp_read_write 场景下的压测结果。注:右滑可以看到每个指标的具体含义。

Threads started!

[ 10s ] thds: 64 tps: 5028.08 qps: 100641.26 (r/w/o: 70457.59/20121.51/10062.16) lat (ms,95%): 17.32 err/s: 0.00 reconn/s: 0.00
# thds 是并发线程数。tps 是每秒事务数。qps 是每秒操作数,等于 r(读操作)加上 w(写操作)加上 o(其他操作,主要包括 BEGIN 和 COMMIT)。lat 是延迟,(ms,95%) 是 95% 的查询时间小于或等于该值,单位毫秒。err/s 是每秒错误数。reconn/s 是每秒重试的次数。
[ 20s ] thds: 64 tps: 5108.93 qps: 102192.09 (r/w/o: 71533.28/20440.64/10218.17) lat (ms,95%): 17.32 err/s: 0.00 reconn/s: 0.00
[ 30s ] thds: 64 tps: 5126.50 qps: 102505.50 (r/w/o: 71756.30/20496.60/10252.60) lat (ms,95%): 17.32 err/s: 0.00 reconn/s: 0.00
[ 40s ] thds: 64 tps: 5144.50 qps: 102907.20 (r/w/o: 72034.07/20583.72/10289.41) lat (ms,95%): 17.01 err/s: 0.00 reconn/s: 0.00
[ 50s ] thds: 64 tps: 5137.29 qps: 102739.80 (r/w/o: 71916.99/20548.64/10274.17) lat (ms,95%): 17.01 err/s: 0.00 reconn/s: 0.00
[ 60s ] thds: 64 tps: 4995.38 qps: 99896.35 (r/w/o: 69925.98/19979.61/9990.75) lat (ms,95%): 17.95 err/s: 0.00 reconn/s: 0.00
SQL statistics:
    queries performed:
        read:                            4276622 # 读操作的数量
        write:                           1221892 # 写操作的数量
        other:                           610946  # 其它操作的数量
        total:                           6109460 # 总的操作数量,total = read + write + other
    transactions:                        305473 (5088.63 per sec.)    # 总的事务数(每秒事务数)
    queries:                             6109460 (101772.64 per sec.) # 总的操作数(每秒操作数)
    ignored errors:                      0      (0.00 per sec.)       # 忽略的错误数(每秒忽略的错误数)
    reconnects:                          0      (0.00 per sec.)       # 重试次数(每秒重试的次数)

General statistics:
    total time:                          60.0301s  # 总的执行时间
    total number of events:              305473    # 执行的 event 的数量
                                                   # 在 oltp_read_write 中,默认参数下,一个 event 其实就是一个事务

Latency (ms):
         min:                                    5.81 # 最小耗时
         avg:                                   12.57 # 平均耗时
         max:                                  228.87 # 最大耗时
         95th percentile:                       17.32 # 95% event 的执行耗时
         sum:                              3840044.28 # 总耗时

Threads fairness:
    events (avg/stddev):           4773.0156/30.77  # 平均每个线程执行 event 的数量
                                                    # stddev 是标准差,值越小,代表结果越稳定。
    execution time (avg/stddev):   60.0007/0.01     # 平均每个线程的执行时间

输出中,重点关注三个指标:

  1. 每秒事务数,即我们常说的 TPS。
  2. 每秒操作数,即我们常说的 QPS。
  3. 95% event 的执行耗时。

TPS 和 QPS 反映了系统的吞吐量,越大越好。执行耗时代表了事务的执行时长,越小越好。在一定范围内,并发线程数指定得越大,TPS 和 QPS 也会越高。