sysbench是一个基于LuaJIT脚本的多线程基准测试工具。2004年由Peter Zaitsev(Percona公司创始人)开发,在其0.5版本中可以使用Lua脚本实现OLTP测试。2016年重构了sysbench代码,并在2017年2月针对新的硬件环境发布了1.0版本,优化了测试性能(是0.5版本的6倍,可以压测60万TPS)和可扩展性(无Mutex、无共享计数器、多线程扩展性更强)。
sysbench不仅可用于数据库基准测试,也可用于服务器的其他工作负载基准测试。本文主要以1.0版本为例介绍sysbench。在新的Release版本下,sysbench新增与优化了如下一些特性。
执行如下命令,设置yum repo仓库/etc/yum.repos.d/akopytov_sysbench.repo,并直接使用yum安装。
# RHEL/CentOS
[root@localhost~]# curl -s https://packagecloud.io/install/repositories/akopytov/ sysbench/script.rpm.sh | sudo bash
[root@localhost~]# sudo yum -y install sysbench
手动下载RPM包来安装(仅限RHEL/CentOS),但是在安装sysbench前需要先安装依赖包,然后再安装该RPM包。
[root@localhost~]# yum install mysql-libs postgresql-libs -y
[root@localhost~]# rpm -Uvh sysbench-1.0.7-13.el6.x86_64.rpm –nodeps
由于sysbench编译时依赖libmysqlclient动态链接库,所以要选择对应版本的sysbench,或者使用软链接:
[root@localhost~]# ln -s /usr/lib64/mysql/libmysqlclient.so.18 /usr/lib64/ libmysqlclient_r.\ so.16
安装依赖的编译环境:
# RHEL/CentOS
[root@localhost~]# yum -y install make automake libtool pkgconfig libaio-devel vim-\
common git
## For MySQL support, replace with mysql-devel on RHEL/CentOS 5
[root@localhost~]# yum -y install mariadb-devel
## For PostgreSQL support
[root@localhost~]# yum -y install postgresql-devel
最新的sysbench程序包地址为https://github.com/akopytov/sysbench/releases,直接下载并解压缩程序包:
[root@localhost~]# wget
https://github.com/akopytov/sysbench/archive/1.0.13.tar.gz
[root@localhost~]# tar zxf sysbench-1.0.13.tar.gz
编译安装:
[root@localhost~]# cd sysbbench-1.0.13
[root@localhost~]# ./autogen.sh
## Add –with-pgsql to build with PostgreSQL support
[root@localhost~]# ./configure
[root@localhost~]# make
[root@localhost~]# make install
查看版本信息,如果可以正常查看到版本信息而不报错,则说明sysbench安装成功。
[root@localhost~]# sysbench –version
本节通过几个测试案例简单介绍如何使用sysbench对MySQL数据库进行压力测试。
sysbench除能压测数据库性能之外,还能对其他一些测试对象进行性能测试,包括CPU、内存、线程等的压测,限于篇幅,这里不详细介绍,读者可以参考链接:Sysbench – Gentoo Wiki来进一步了解。
在测试前,请先创建好MySQL账户qbench@127.0.0.1(密码为qbench),确保该账户可以正常连接到数据库,并且拥有sbtest库的所有权限。下面就利用4个并发线程,对一个MySQL实例上的32个500万行数据的表(sbtest1, sbtest2, … ,sbtest32)进行180s的压力测试,以查看MySQL数据库在压力下的表现。
可以直接使用Lua脚本前缀作为testname,使用prepare命令造数。
[root@localhost~]# sysbench –db-driver=mysql –time=180 –threads=4 –report-interval=1\ –mysql-host =127.0.0.1 –mysql-port=3306 –mysql-user=qbench –mysql-password=qbench\ –mysql-db= sbtest –tables=32 –table-size=5000000 oltp_read_write –db-ps-mode=disable\ prepare
1.oltp_read_write
该测试案例对应sysbench 0.5版本的oltp.lua脚本,用于测试数据库的TPS性能。
[root@localhost~]# sysbench –db-driver=mysql –time=180 –threads=4 –report-interval=1 –mysql-host =127.0.0.1 –mysql-port=3306 –mysql-user=qbench –mysql-password=qbench –mysql -db =sbtest –tables=32 –table-size=5000000 oltp_read_write –db-ps-mode=disable run
2.oltp_read_only
该测试案例对应sysbench 0.5版本的select.lua脚本,用于测试数据库的只读性能。
[root@localhost~]# sysbench –db-driver=mysql –time=180 –threads=4 –report-interval=1 –mysql-host=127.0.0.1 –mysql-port=3306 –mysql-user=qbench –mysql-password=qbench –mysql-db=sbtest –tables=32 –table-size=5000000 oltp_read_only –db-ps-mode=disable run
3.oltp_delete
该测试案例对应sysbench 0.5版本的delete.lua脚本,用于测试数据库的删除性能。
[root@localhost~]# sysbench –db-driver=mysql –time=180 –threads=4 –report-interval=1 –mysql-host=127.0.0.1 –mysql-port=3306 –mysql-user=qbench –mysql-password=qbench –mysql-db=sbtest –tables=32 –table-size=5000000 oltp_delete –db-ps-mode=disable run
4.oltp_update_index
该测试案例对应sysbench 0.5版本的update_index.lua脚本,用于测试数据库的更新索引性能。
[root@localhost~]# sysbench –db-driver=mysql –time=180 –threads=4 –report-interval=1 –mysql-host=127.0.0.1 –mysql-port=3306 –mysql-user=qbench –mysql-password=qbench –mysql-db=sbtest –tables=32 –table-size=5000000 oltp_update_index –db-ps-mode=disable run
5.oltp_update_non_index
该测试案例对应sysbench 0.5版本的update_non_index.lua脚本,用于测试数据库的更新非索引字段性能。
[root@localhost~]# sysbench –db-driver=mysql –time=180 –threads=4 –report-interval=1 –mysql-host=127.0.0.1 –mysql-port=3306 –mysql-user=qbench –mysql-password=qbench –mysql-db=sbtest –tables=32 –table-size=5000000 oltp_update_non_index –db-ps-mode=disable run
6.oltp_insert
该测试案例对应sysbench 0.5版本的insert.lua脚本,用于测试数据库的插入性能。
[root@localhost~]# sysbench –db-driver=mysql –time=180 –threads=4 –report-interval=1 –mysql-host=127.0.0.1 –mysql-port=3306 –mysql-user=qbench –mysql-password=qbench –mysql-db=sbtest –tables=32 –table-size=5000000 oltp_insert –db-ps-mode=disable run
7.oltp_write_only
该测试案例是sysbench 1.0.x版本新增的,与原来的oltp.lua相比,少了select部分。
[root@localhost~]# sysbench –db-driver=mysql –time=180 –threads=4 –report-interval=1 –mysql-host=127.0.0.1 –mysql-port=3306 –mysql-user=qbench –mysql-password=qbench –mysql-db=sbtest –tables=32 –table-size=5000000 oltp_write_only –db-ps-mode=disable run
使用cleanup命令清理prepare和run产生的数据,实际上是删除对应的表。
[root@localhost~]# sysbench –db-driver=mysql –time=180 –threads=4 –report-interval=1 –mysql-host=127.0.0.1 –mysql-port=3306 –mysql-user=qbench –mysql-password=qbench –mysql-db=sbtest –tables=32 –table-size=5000000 oltp_read_write –db-ps-mode=disable cleanup
sysbench命令语法如下:
sysbench [options]… [testname] [command]
下面逐一介绍相关选项。
1.常规选项
2.伪随机数创建选项
3.日志选项
4.常规数据库选项
5.MySQL选项
6.pgsql选项
7.其他选项
通过使用如下命令来查看额外的关于测试名称(事务模型)命令选项,只需要任意指定一个测试名称即可。
# 指定oltp_read_write测试名称来查看额外的帮助选项
[root@localhost ]# sysbench oltp_read_write help
……
oltp_read_write options:
–distinct_ranges=N Number of SELECT DISTINCT queries per transaction [1]
–sum_ranges=N Number of SELECT SUM() queries per transaction [1]
–skip_trx[=on|off] Don’t start explicit transactions and execute all queries in the AUTOCOMMIT mode [off]
……
各选项解释如下。
提示:
编辑
testname用于指定sysbench的基准测试名称。基准测试包括:
提示:在实际执行时,对于Lua新格式脚本,可以只写脚本名称(不写.lua后缀),如oltp_read_only,不再需要像sysbench 0.5及之前版本那样使用–test选项来指定。
1.sysbench Lua脚本介绍
Sysbench 1.0.x版本中的Lua脚本代码比0.5.x版本工整得多,并且对结构进行了重新设计,大部分SQL语句都被整合到了oltp_common.lua脚本中集中定义,其他Lua脚本只需要加载这个脚本进行调用即可。另外,还对原来的delete.lua、select.lua、update*.lua、insert.lua脚本中的SQL语句进行了改进,将其嵌套到begin和commit语句中。
通过RPM包安装的sysbench 1.0.x版本中的Lua脚本有两个目录,如下所示。
[root@localhost~]# ls -lh /usr/share/sysbench/ /usr/share/sysbench/tests/include/\ oltp_legacy
/usr/share/sysbench/: #对于sysbench 1.0.x版本,建议使用这个目录下的最新的Lua脚本。不过该脚本使用prepare命令执行语句,需要创建大量的prepare命令对象,调整参数的值
total 64K
-rwxr-xr-x 1 root root 1.5K May 15 22:14 bulk_insert.lua
-rw-r–r– 1 root root 14K May 15 22:14 oltp_common.lua
-rwxr-xr-x 1 root root 1.1K May 15 22:14 oltp_delete.lua
-rwxr-xr-x 1 root root 2.0K May 15 22:14 oltp_insert.lua
-rwxr-xr-x 1 root root 1.3K May 15 22:14 oltp_point_select.lua
-rwxr-xr-x 1 root root 1.7K May 15 22:14 oltp_read_only.lua
-rwxr-xr-x 1 root root 1.8K May 15 22:14 oltp_read_write.lua
-rwxr-xr-x 1 root root 1.1K May 15 22:14 oltp_update_index.lua
-rwxr-xr-x 1 root root 1.2K May 15 22:14 oltp_update_non_index.lua
-rwxr-xr-x 1 root root 1.5K May 15 22:14 oltp_write_only.lua
-rwxr-xr-x 1 root root 1.9K May 15 22:14 select_random_points.lua
-rwxr-xr-x 1 root root 2.1K May 15 22:14 select_random_ranges.lua
drwxr-xr-x 4 root root 4.0K Jun 15 15:53 tests
/usr/share/sysbench/tests/include/oltp_legacy: # 对于sysbench 1.0.x版本,在这个目录下保留了一些兼容之前版本写法的Lua脚本
total 52K
-rw-r–r– 1 root root 1.2K May 15 22:14 bulk_insert.lua
-rw-r–r– 1 root root 4.6K May 15 22:14 common.lua
-rw-r–r– 1 root root 366 May 15 22:14 delete.lua
-rw-r–r– 1 root root 1.2K May 15 22:14 insert.lua
-rw-r–r– 1 root root 3.0K May 15 22:14 oltp.lua
-rw-r–r– 1 root root 368 May 15 22:14 oltp_simple.lua
-rw-r–r– 1 root root 527 May 15 22:14 parallel_prepare.lua
-rw-r–r– 1 root root 369 May 15 22:14 select.lua
-rw-r–r– 1 root root 1.5K May 15 22:14 select_random_points.lua
-rw-r–r– 1 root root 1.6K May 15 22:14 select_random_ranges.lua
-rw-r–r– 1 root root 369 May 15 22:14 update_index.lua
-rw-r–r– 1 root root 578 May 15 22:14 update_non_index.lua
关于Lua语法请参考:http://www.runoob.com/lua/lua-tutorial.html。
2.自定义Lua脚本
为了实现自定义测试,读者也可以自定义Lua脚本,使用sysbench进行测试。
下面是一个简单的示例。
function prepare()
db_query(“CREATE TABLE t (a INT)”)
db_query(“INSERT INTO t VALUES (1)”)
end
function event()
db_query(“UPDATE t SET a = a + ” .. sb_rand(1, 1000))
end
function cleanup()
db_query(“DROP TABLE t”)
end
使用sysbench测试如下:
# calls prepare()
[root@localhost~]# sysbench –test=test.lua prepare
# calls event() in a loop
[root@localhost~]# sysbench –test=test.lua –num-threads=16 –report-interval=1 run
[ 1s] threads: 16, tps: 0.00, reads: 0.00, writes: 13788.65, response time: 1.43ms (95%)
[ 2s] threads: 16, tps: 0.00, reads: 0.00, writes: 14067.56, response time: 1.40ms (95%)
…
$ sysbench –test=test.lua cleanup # calls cleanup()
command将由sysbench传递给内置的testname或testname指定的Lua脚本。该命令指定testname需要执行的操作。
以下是典型的测试命令及其描述。
下面详细介绍使用sysbench测试MySQL数据库的输出结果。
[root@localhost~]# sysbench –db-driver=mysql –time=10 –threads=4 –report-interval=1\ –mysql-host=127.0.0.1 –mysql-port=3306 –mysql-user=qbench –mysql-password=qb
[14/480]
ysql-db=sbtest –tables=32 –table-size=50000 oltp_read_write –db-ps-mode=disable run
sysbench 1.0.7 (using bundled LuaJIT 2.1.0-beta2)
Running the test with following options:
Number of threads: 4
Report intermediate results every 1 second(s)
Initializing random number generator from current time
Initializing worker threads…
Threads started!
[ 1s ] thds: 4 tps: 374.23 qps: 7533.43 (r/w/o: 5280.08/977.98/1275.36) lat (ms,95%): 17.95 err/s: 0.00 reconn/s: 0.00
[ 2s ] thds: 4 tps: 329.07 qps: 6604.49 (r/w/o: 4622.04/880.20/1102.25) lat (ms,95%): 21.11 err/s: 0.00 reconn/s: 0.00
[ 3s ] thds: 4 tps: 362.00 qps: 7225.05 (r/w/o: 5054.04/943.01/1228.01) lat (ms,95%): 18.61 err/s: 0.00 reconn/s: 0.00
[ 4s ] thds: 4 tps: 392.00 qps: 7847.05 (r/w/o: 5494.04/1069.01/1284.01) lat (ms,95%): 17.63 err/s: 0.00 reconn/s: 0.00
[ 5s ] thds: 4 tps: 331.01 qps: 6602.18 (r/w/o: 4625.12/894.02/1083.03) lat (ms,95%): 20.37 err/s: 0.00 reconn/s: 0.00
[ 6s ] thds: 4 tps: 334.99 qps: 6712.77 (r/w/o: 4698.84/929.97/1083.96) lat (ms,95%): 19.65 err/s: 0.00 reconn/s: 0.00
[ 7s ] thds: 4 tps: 356.97 qps: 7149.40 (r/w/o: 5002.58/985.92/1160.90) lat (ms,95%): 19.29 err/s: 0.00 reconn/s: 0.00
[ 8s ] thds: 4 tps: 333.01 qps: 6657.20 (r/w/o: 4663.14/926.03/1068.03) lat (ms,95%): 20.37 err/s: 0.00 reconn/s: 0.00
[ 9s ] thds: 4 tps: 347.03 qps: 6950.59 (r/w/o: 4860.41/972.08/1118.09) lat (ms,95%): 20.37 err/s: 0.00 reconn/s: 0.00
[ 10s ] thds: 4 tps: 342.97 qps: 6821.44 (r/w/o: 4773.61/932.92/1114.91) lat (ms,95%): 19.29 err/s: 0.00 reconn/s: 0.00
SQL statistics:
queries performed:
read: 49084
write: 9513
other: 11523
total: 70120
transactions: 3506 (350.33 per sec.)
queries: 70120 (7006.63 per sec.)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
General statistics:
total time: 10.0062s
total number of events: 3506
Latency (ms):
min: 4.56
avg: 11.41
max: 39.24
95th percentile: 19.65
sum: 39997.58
Threads fairness:
events (avg/stddev): 876.5000/5.22
execution time (avg/stddev): 9.9994/0.00
Sysbench测试输出结果主要分为三部分:
在sysbench测试正常开始以后,首先输出的是sysbench的版本、压测线程个数、每隔几秒输出一次中间结果、随机数初始化等相关信息。
在指定了–report-interval参数以后,每隔report-interval时间输出一次中间统计结果,如下所示。
[ 6s ] thds: 4 tps: 334.99 qps: 6712.77 (r/w/o: 4698.84/929.97/1083.96) lat (ms,95%): 19.65 err/s: 0.00 reconn/s: 0.00
在sysbench全部测试完成以后,将输出整体压测的统计结果。主要分为四部分:
(1)SQL统计结果
该项输出结果包括sysbench发起的读/写/其他/总计SQL查询数量、总计事务数及每秒事务数、总计请求数及每秒请求数、总计错误数及每秒错误数、总计重连接数及每秒重连接数。
SQL statistics:
queries performed:
read: 49084
write: 9513
other: 11523
total: 70120
transactions: 3506 (350.33 per sec.)
queries: 70120 (7006.63 per sec.)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
(2)通用统计值
该项输出结果包括总计执行的时间、所有的事件数量(这里对应的是发起的MySQL事务数)。
General statistics:
total time: 10.0062s
total number of events: 3506
(3)延迟时间统计结果
该项输出结果包括延迟时间最低值、平均值、最高值、第95%位值、总计值。
Latency (ms):
min: 4.56
avg: 11.41
max: 39.24
95th percentile: 19.65
sum: 39997.58
(4)压测线程统计结果
该项输出结果包括每个压测线程的平均事件数及标准差、每个事务的平均执行时间及标准差。
Threads fairness:
events (avg/stddev): 876.5000/5.22
execution time (avg/stddev): 9.9994/0.00