MySQL压力测试方案--测试工具

发布时间: 更新时间: 总字数:4137 阅读时间:9m 作者: 分享

本博客主要介绍MySQL压力测试的方法,主要是总结MySQL测试的一些先决条件和重要工具。

MySQL压力测试的先决条件

业务复杂性(考虑生成环境中多业务共存和业务特性等)

数据真实性(统计业务的真实数据包括:1. 表的记录量2. 模拟业务最大20条SQL语句,按比例模拟3. 模拟事物)

流量真实性(1. 模拟数据库连接数1-3倍业务量2. SQL语句真实性)

环境真实性(1. 网络带宽和时延2. CPU/IO/内存,可以安装生产环境打折,如CPU核数1/8等)

结果可靠性(1. 模拟SQL质量2. 数据模拟质量3. 事物模拟质量4. 结果取1/2或1/3)

测试工具下载

mydbtest_linux64.bin软件下载地址:mydbtest_linux64或平民软件官方下载

测试demo

创建数据库

CREATE DATABASE IF NOT EXISTS data1 DEFAULT CHARSET utf8 COLLATE utf8_general_ci ;

USE data1;

CREATE TABLE table1(
  id INT(11) PRIMARY KEY,
  col1 VARCHAR(20) NOT NULL,
  START DATE);

创建配置文件insert.cnf

option
  user data1/data1pwd@127.0.0.1:3306:data1
  time 5m
  loop 1000
  log log_test_%p.log
declare
  v_id SEQ 1 1000000000
  v_col1 CHAR 10 20
  v_start DATE -1000 0
begin
  INSERT INTO table1(id, col1, start) VALUES(:v_id, :v_col1, :v_start);
end

上述配置文件实现向数据库插入1000条记录,对配置文件编写后续单独说明。

压力测试命令帮助命令

[root@xianbin mysql]# ./mydbtest_linux64.bin 

Usage: mysqldbtest keyword=value [,keyword=value,...]

Valid Keywords:
   user    = username/password@tnsname for source and target.
   query   = select query (first col as key, second as double value).
   degree  = parallel degree for multiple threads test

压力测试命令

[root@xianbin insert]# ./mydbtest_linux64.bin query=insert.cnf degree=8
Summary: SQL01 exec=8000, rows=8000=100/e, avg=3590 us
Summary: exec=2212/s, qtps=2212/s
[root@xianbin insert]# 

测试工具有两个参数来指定:

«query»:表示测试用例的配置文件;

«degree»:表示测试的并行度,及执行query的线程数。

测试命令为:

./mydbtest_linux64.bin query=test.cnf degree=8

注:degree(并行度)最大可以是16348,默认为1,通常一台服务器就能够制造出足够的数据库压力。

测试日志及说明

[root@xianbin insert]# ll
total 3472
-rw-r--r--. 1 root root     255 Sep  6 04:41 insert.cnf
-rw-r--r--. 1 root root    1548 Sep  6 04:44 log_test_00001.log
-rw-r--r--. 1 root root    1352 Sep  6 04:44 log_test_00002.log
-rw-r--r--. 1 root root    1548 Sep  6 04:44 log_test_00003.log
-rw-r--r--. 1 root root    1450 Sep  6 04:44 log_test_00004.log
-rw-r--r--. 1 root root    1548 Sep  6 04:44 log_test_00005.log
-rw-r--r--. 1 root root    1254 Sep  6 04:44 log_test_00006.log
-rw-r--r--. 1 root root    1548 Sep  6 04:44 log_test_00007.log
-rw-r--r--. 1 root root    1450 Sep  6 04:44 log_test_00008.log
-rwxr-xr-x. 1 root root 3514808 Sep  6 03:23 mydbtest_linux64.bin
[root@xianbin insert]# cat log_test_00001.log 
MYDBTEST: MySQL Database Test Utility , Release 1.0.1
(@) Copyright Lou Fangxin (AnySQL.net) 2012 - 2013, all rights reserved.
2015-09-06 04:44:00 ======================== CASE SUMMARY ========================
2015-09-06 04:44:00 SQL01  exe=1000 fail=0 row=1000 ela=3620 ms avg=3620 us
2015-09-06 04:44:00 SQL01    2 ms  exec=       6, ela=         9 ms, avg=    1543 us, pct=  0,  0
2015-09-06 04:44:00 SQL01    3 ms  exec=     173, ela=       480 ms, avg=    2776 us, pct= 17, 17
2015-09-06 04:44:00 SQL01    4 ms  exec=     636, ela=      2199 ms, avg=    3459 us, pct= 63, 81
2015-09-06 04:44:00 SQL01    5 ms  exec=     156, ela=       672 ms, avg=    4309 us, pct= 15, 97
2015-09-06 04:44:00 SQL01    6 ms  exec=      18, ela=        96 ms, avg=    5378 us, pct=  1, 98
2015-09-06 04:44:00 SQL01    7 ms  exec=       3, ela=        19 ms, avg=    6666 us, pct=  0, 99
2015-09-06 04:44:00 SQL01    8 ms  exec=       1, ela=         7 ms, avg=    7454 us, pct=  0, 99
2015-09-06 04:44:00 SQL01   11 ms  exec=       2, ela=        20 ms, avg=   10354 us, pct=  0, 99
2015-09-06 04:44:00 SQL01   20 ms  exec=       2, ela=        39 ms, avg=   19708 us, pct=  0, 99
2015-09-06 04:44:00 SQL01   21 ms  exec=       1, ela=        20 ms, avg=   20155 us, pct=  0, 99
2015-09-06 04:44:00 SQL01   25 ms  exec=       1, ela=        24 ms, avg=   24416 us, pct=  0, 99
2015-09-06 04:44:00 SQL01   30 ms  exec=       1, ela=        29 ms, avg=   29903 us, pct=  0,100
2015-09-06 04:44:00 Total  tran=1000=274/s, qtps=1000=274/s, ela=3613 ms, avg=3613 us
[root@xianbin insert]# 

其中SQL01 exe=1000 fail=0 row=1000 ela=3620 ms avg=3620 us表示,SQL01这个线程共执行1000次,失败0次,对数据库操作1000行,总时长3620 ms,平均时长3620 us(3.63ms)。

Total tran=1000=274/s, qtps=1000=274/s, ela=3613 ms, avg=3613 us表示,总共执行1000个事物,平均274个每秒,单线程压倒274个TPS,若要估算中TPS,只需要乘以并行度,当前MySQL实例的并行度为2192的样子。

SQL01 2 ms exec= 6, ela= 9 ms, avg= 1543 us, pct= 0,

0表示在0-2ms共执行6次,总是长9ms,平均1543us,占总比例0%,累计比例0%。

SQL01 3 ms exec= 173, ela= 480 ms, avg= 2776 us, pct= 17,

17表示在2-3ms共执行173次,总是长480ms,平均2776us,占总比例17%,累计比例17%。

SQL01 4 ms exec= 636, ela= 2199 ms, avg= 3459 us, pct= 63,

81表示在3-4ms共执行636次,总是长2199ms,平均3459us,占总比例63%,累计比例81%。

依次类推。。。

配置文件说明

配置文件中包含除并发数以外的所有测试信息,主要包含以下几部分:

OPTION
控制选项
DECLARE
 变量定义
BEGIN
 SQL 语句
END

1. 控制选项

共有10个可以配置控制选项,下面分别介绍:

  • user

test/testpwd@localhost:3306:test,数据库连接信息,MySQL和Oracle通用,格式为:用户名/密码@主机IP:端口号:数据库名或实例名

  • loop

100000000,测试用例的执行次数,默认值为1亿次,用来控制数据测试次数时有用,其它是建议采用时间控制。

  • name

test_01,压力测试用例名称,仅显示在测试工具的日志文件里。

  • wait

0.1,两次执行(所有定义的语句被执行算一次)之间暂停的时间间隔,单位为0.1毫秒,不是两个SQL语句之间的暂停时间。默认值为0表示没有任何停顿,用大并发测试时需要指定一个暂停时间,若定义则在超过1000个并发线程压测时会计算一个默认值。

  • log

log_%p.log,输出的日志文件的名称。如果未定义则输出到当前屏幕,文件名中可以用»%p»表示线程号,以便每个并发线程创建一个独立的日志文件。如果不想输出任何信息,则可以定义为»/dev/null»(Linux的黑洞)。

  • show

整形数值,时延信息报告频率,默认值是300s,即每个5分钟输出一段测试报告。

  • psmode

YES/NO,使用绑定变量模式,此选项只针对MySQL版本,默认值是关闭(NO),在MySQL上执行时所有的变量会被进行宏替换处理;如果设置为YES,则使用绑定变量的接口来进行参数传递。

  • tran

OFF/ON,事物模式开关,默认值为OFF,即运行在自动提交模式,每一个SQL会被当作一个事物,执行成功则提交;如果设置为打开ON,则第一条SQL执行前会有一个开启事物的调用,所有SQL执行完成后,会有一个事物提交命令。

  • commit

整形数值,事物大小参数,默认值为1,每执行一次测试发一次提交命令,在测试中我们通常将一个事物的SQL写在一起,这个值很合适的;当我们在模拟测试数据时,不妨调大到100或1000,以加快测试数据生成过程,此参数只在事物模式下有效。

  • time

测试时间,默认值为3600,即1小时。可以用»m»或»h»来简化时间。比如»5m»表示5分钟,»2h»表示两小时。

2. 变量定义

该工具可以让用户定义一些变量,并且设置随机值得取值范围,然后用在SQL语句中用英文冒号加变量名来加以应用,Oracle和MySQL语法相同。共有9中不同的变量类型可以选择,变量定义的语法如下:

变量名 VARTYPE 值列表
变量名 VARTYPE 最小值 最大值 

其中变量类型可以是»SEQ»、»INT»、»INTLIST»、»CHAR»、»STRLIST»、»FLOAT»、»DOUBLE»、»DATE»、»TIMESTAMP»、»DATETIME»中的任何一种,下面分别介绍各种变量类型的含义:

  • SEQ

自动递增的32位整数,从最小值开始一直到最大值,如果测试用例执行的次数超过最大值,则会从头开始循环使用,同Oracle中的Sequence对象。例如

v_seq1 seq 1 100000000
v_seq2 seq 1 100000000
  • INT

自动递增的32位整数,在最小值和最大值之间自动选取一个随机值,例如:

v_int1 INT 1 100000000
v_int2 INT 1 100000000
  • INTLIST

从给定的值中自动选取一个整数值,多个值之间用逗号分隔,两个值中间不能带空格。例如:

v_int1 INTLIST 1,2,3,4,5,6,7,8
v_int2 INTLIST 1,1,2,2,3,3,4,4,5,5,6,7,8
  • CHAR

字符串类型,自动生成值在A-Z之间的字母填充,需要定义最小长度和最大长度,最大长度是255个字节,例如:

v_str1 CHAR 10 20
v_str2 CHAR 4 4
  • STRLIST

从给定的字符串中自动选取一个字符串,多个字符串之间用逗号分隔。要求字符串的值不能包含空格,两个字符串之间不能和带空格。例如:

v_str1 STRLIST sun,mon,tue,wed,thr,fri,sat
v_str2 STRLIST male,female
  • FLOAT

低精度浮点数,在最小值和最大值之间自动选取一个随机数。例如:

v_float1 FLOAT 1 100000000
v_float2 FLOAT 1 100000000
  • DOUBLE

高精度浮点数,在最小值和最大值之间自动选取一个随机值。例如:

v_dbl1 DOUBLE 1 100000000
v_dbl2 DOUBLE 1 100000000
  • DATE

自动生成的具有格式(YYYY-MM-DD)的字符串,需要指定日期范围,开始日期为当前日期减最小值,结束日期为当前日期加最大值。例如指定值»-10»表示开始日期为10天前,指定»10»表示10天后。例如:

v_date1 DATE -10 10
v_date2 DATE -30 30
  • TIMESTAMP

自动生成的具有日期格式(YYYY-MM-DD HH24:MM:SS)的字符串,需要指定日期范围,开始日期为当前日期减最小值,结束日志为当前日期加最大值。例如指定值»-10»表示开始日期为10天前,指定»10»表示10天后。例如:

v_datetime1 TIMESTAMP -10 10
v_datetime2 TIMESTAMP -10 10
  • DATETIME

同上

v_datetime DATETIME -1 0

是用不同的变量类型,可以很容易的模拟真实的数据分布情况来生成测试数据,即使不从生产库copy数据也可以精确地测速数据库性能。

3. SQL语句

  • 基本语法

SQL语句包括SELECT、INSERT、UPDATE和DELETE语句,也可以用»{«和»}«将一段存储过程括起来(见Oracle数据库),不同语句之间用»;«分割。

begin
  select col1 from table1 where col1 = :id;
  select col1, col2 from table1 where col1 = :id;
  select * from table1 where col1 = :id;
  { begin update table1 set col2=col2 – 1 where col1 = :id;
    update table1 set col2=col2 + 1 where col1 = :id + 1; end; }
end

如果希望SQL不是每次都执行,而是以特定的概率执行,可以使用»RANDOM n»来控制执行比例,»n»指的是1和100之间的一个比例制。例如:

begin
  select col1 from table1 where col1 = :id;
  RANDOM 50 select col1, col2 from table1 where col1 = :id;
  RANDOM 20 select * from table1 where col1 = :id;
end

如果你希望用一个查询(通常是返回单行的SQL语句)来为变量赋值,只需要在SQL语句前加上»SERVAR»关键字,就可以将变量值放到与返回值同名的变量中。例如:

begin
  SETVAR select col1 id from table1;
  select col1, col2 from table1 where col1 = :id;
  select * from table1 where col1 = :id;
end
  • 事务控制

使用»tran»控制选项,可以将所有的SQL语句方法一个事物中执行,或者运行在自动提交模式下。在真实的测试中,我们需要部分SQL运行在自动提交模式下,部分SQL则可以自由组合成为一个事物来执行。因此,需要有一种机制来自定义事物的开始和结束。

在mysqldbtest.bin中,一个使用»start»来显示的表示一个事物的开始,用»commit»或»rollback»来表示一个事物的结束。例如:

option
  name tran_demo
  loop 2000
  user /@::test
declare
  a int 20000 30000
  b int 20000 30000
begin
  start;
    select * from table1 where col1 = :a;
    random 50 select * from table1 where col1 = :b;
  commit;
end

参考

Home Archives Categories Tags Docs