为什么80%的码农都做不了架构师?>>>   

前言

针对数据库的性能测试,loadrunner本身支持sql server和oracle数据库,这两种数据库可以用loadrunner直接录制进行测试。而我们项目中使用的是mysql数据库,针对用loadrunner测试mysql数据库的方法网上也有很多介绍文章,主要有两种方案。一种是利用ODBC连接测试mysql,但是这种方法配置比较麻烦,如果要录制的话需要安装支持ODBC连接的查询分析器,这工具不好找,能找到的也只能算凑合能用。如果大家有兴趣试试这种方法,可以上网搜搜,学习配置一下。另外一种方法是利用mysql lib库进行测试,这也是loadrunner推荐的测试方法,模拟mysql客户端连接数据库进行增删改查的操作进行测试,这种方法配置简单,不过不能通过录制的方法得到测试脚本,需要一定的编程基础,手工编写测试脚本,当然,可以参考loadrunner的联机帮助+google进行。下面主要介绍第二种方法,如何利用mysql lib库连接mysql数据库进行性能测试。

配置loadrunner连接使用mysql

Loadrunner不能直接跟mysql进行通信,在使用loadrunner之前需要将一些库文件和dll文件添加到loadrunner的安装目录中。这些文件需要添加到所有需要执行测试脚本的系统中,包括需要使用loadrunner控制器,虚拟用户生成器和loadrunner代理的测试负载机。

在附件中的MySQL LoadRunner libraries.zip中包含两个文件夹,bin和include。将这两个文件夹覆盖loadrunner安装目录中的bin和include两个文件夹(将bin和include文件夹中的文件分别拷贝到loadrunner安装目录中对应的bin和include文件夹中也可以)。Loadrunner安装目录通常是下面两种格式:

C:Program Files (x86)HPLoadRunner(32位操作系统) 和 C:Program FilesHPLoadRunner(64位操作系统)


然后,在编写测试脚本时,就需要引用这些库文件了,具体操作如下:

  • 在loadrunner脚本中,需要将下面这行代码添加到vuser_init()这是初始化函数之前,这样做是为了让loadrunner在后续的操作中都能引用这些库文件。

1

#include "Ptt_MySQL.h";

  • 还需要用一个函数来加载dll文件到内存中,将下面这行代码添加到需要进行连接数据库操作之前,这样才能让loadrunner连接到mysql数据库。

1

lr_load_dll ("libmysql.dll");

这行代码最好添加在vuser_init()函数中。

  • 我们还需要配置连接数据库的详细信息。

1
2
3
4
5

#define MYSQLSERVER "SERVER_NAME"
#define MYSQLUSERNAME "USER_NAME"
#define MYSQLPASSWORD "PASSWORD"
#define MYSQLDB "SCHEMA_NAME"
#define MYSQLPORT "PORT"

用实际的mysql数据库连接信息替换引号中的参数值。

  • 现在,vuser_init()函数应该看起来像这个样子。


到现在,已经做好了loadrunner连接数据库的准备,可以对mysql数据库进行增、删、改、查的操作了。

用loadrunner进行mysql数据库的查询操作

现在,我们可以在loadrunner脚本中插入任意的函数来进行连接并查询mysql数据库了。下面是一段示例,在Action()函数中如何进行连接mysql数据库并进行查询的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

//Declare MySQL Elements
char sqQuery[512]; // The MySQL query to be executed #定义一个字符数组存储查询的sql语句
MYSQL *Mconn; // The MySQL connection string #mysql连接字符串
int MyRC; // The MySQL return code #mysql的返回码,可以判断sql语句是否执行成功。
Action()
{
//Create the connection string to connect to the server and relevant database #创建一个连接字符串连接服务器和数据库
Mconn = lr_mysql_connect(MYSQLSERVER, MYSQLUSERNAME, MYSQLPASSWORD, MYSQLDB, atoi(MYSQLPORT));
//Build an SQL query and save the query as sqQuery #构建一个sql语句存储在sqQuery字符数组中
sprintf(sqQuery, "select username, password, secret from loadrunner_db.parameters");
//Execute the SQL query (sqQuery) against the server and database defined as Mconn #执行sql语句
lr_mysql_query(Mconn, sqQuery);
//Save the values returned in the first row of the table #查询的结果会存在一个表中,这里取出第一行的数据。
//N.B. The row/cell values appear to be the "wrong way round" #注意,这里的行和列是颠倒的,相当于返回的数据表中一列数据表示数据库中表的一行数据。
lr_save_string(row[0][0].cell, "sUsername");
lr_save_string(row[1][0].cell, "sPassword");
lr_save_string(row[2][0].cell, "sSecret");
//Output the returned values #打印出查询出来的结果
lr_output_message(lr_eval_string("Username: {sUsername}"));
lr_output_message(lr_eval_string("Password: {sPassword}"));
lr_output_message(lr_eval_string("Secret: {sSecret}"));
//Disconnect from MySQL #断开数据库连接
lr_mysql_disconnect(Mconn);
return 0;
}

提示:可以用lr_mysql_query函数执行任何sql语句,如果是执行的select操作,会有返回数据,返回的数据存储在一个多维数组中,可以用下面的语句将数据取出。

1

row[x][y].cell

注意,这里的行和列是颠倒的,x表示列(第一列是0),y表示行(第一行是0)。

用loadrunner进行mysql数据库的插入操作

插入操作,只需将sql语句换成插入的sql语句即可,其他操作根据实际情况更改。
下面是一段示例代码:

1

sprintf(sqQuery, "insert into loadrunner_db.results (id, username,password) values ('1','tom','123456')";

这段语句是插入一条数据,但实际情况是,我们在测试时可能需要插入很多不同的数据,如果id是主键,用这条数据就会报错,因为主键不能重复。所以我们需要对插入的数据进行参数化,代码就需要改成:

1

sprintf(sqQuery, " insert into loadrunner_db.results (username,password) values("%s","%s")",lr_eval_string("{user}"),lr_eval_string("{pwd}"));

在数据库表中,如果id是主键,我们将id设置成自增长,让其每添加一条数据,id自动加1。
Sprintf函数的作用就是将字符串格式化后存入指定的变量中,那么我们可以将需要参数化的部分格式化处理,然后参数化输入的变量。%s表示格式化成字符串,后面的lr_eval_string("xxx")是输入的参数,每一个参数对应一个%s,用逗号分隔参数,参数化输入的参数xxx,即变成lr_eval_string("{user}"),我们将需要输入的参数全部在user.dat文件中定义即可。
还有其他格式化表示为:%d,double型;%f,float型;%i,int型等等。
Update和delete的操作跟insert类似,参数化方法一样。
一个完成的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

//Declare MySQL Elements
char sqQuery[512];            // The MySQL query to be executed
MYSQL *Mconn;                 // The MySQL connection string
//Declare variables which can be sent to MySQL in this sample script
double dDuration;
int iMIN, iMAX, i, iRand;
Action()
{
lr_start_transaction("0001_Example");
lr_think_time(1);
dDuration=lr_get_transaction_duration("0001_Example");
lr_end_transaction("0001_Example",LR_AUTO);
lr_save_datetime("%H:%M:%S", TIME_NOW, "sTime");
iRand = fRandInt (1,1000000);
//Create the connection string to connect to the server and relevant database
Mconn = lr_mysql_connect(MYSQLSERVER, MYSQLUSERNAME, MYSQLPASSWORD, MYSQLDB, atoi(MYSQLPORT));    //Connect to the MySQL server defined in ....LR_IncludesMySQLSettings.h
//Build an SQL query and save the query as sqQuery
sprintf(sqQuery, "insert into loadrunner_db.results (time, duration, returned_data)"
"values ("%s","%f","%i")",
lr_eval_string("{sTime}"),
dDuration,
iRand);
//Execute the SQL query (sqQuery) against the server and database defined as Mconn
lr_mysql_query(Mconn, sqQuery);
lr_output_message("This SQL statement executed - [%s]",sqQuery);
//Disconnect from MySQL
lr_mysql_disconnect(Mconn);
return 0;
}

如何进行性能测试

以上我们介绍了怎么利用loadrunner连接mysql数据库进行增删改查的操作,那么我们要对数据库进行性能测试该怎么操作呢,有了上面的方法,进行测试就好办多了。
首先,我们先确定测试目标。通过分别对数据库进行增、改、查的操作,测试出最大的并发操作数和最佳并发操作数,以及最大的执行速率和平均执行速率。我们先定义一下,这里的并发操作,并非是同一时刻去操作数据库,而是建立多个连接进行数据库操作,并不一定在同一个时间点操作数据库,所以在脚本中就不设置集合点了。
结合上面的例子,我们需要对脚本进行修改,设置事务以及判断事务是否成功。因为我们需要测试在进行增、改、查时的性能,所以我们将执行sql语句操作设置在一个事务中。因为需要循环的操作,让每个连接处在活动的状态,为了不让频繁的连接、断开数据库,我们将连接数据库和关闭数据库的操作分别放在vuser_init()和vuser_end()函数中,把执行增、改、查的操作放在Action()中,对于连接数据库的操作,我们还需要判断是否连接成功,如果连接失败,做一个标记,在后续的操作中跳过失败的连接,否则会出现脚本错误,影响测试结果。判断连接数据库是否成功的脚本,可以直接将头文件Ptt_MySql.h中的连接数据库的操作函数拷贝到vuser_init()中进行修改,添加一个事务来统计连接成功的次数。
完整脚本示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

#include "Ptt_Mysql.h"
#include "mysql.h"
#include "mysql_com.h"
#include "mysql_time.h"
#include "mysql_version.h"
#include "typelib.h"
#include "my_list.h"
#include "my_alloc.h"
#define MYSQLSERVER "192.168.1.252"
#define MYSQLUSERNAME "root"
#define MYSQLPASSWORD "root"
#define MYSQLDB    "test"
#define MYSQLPORT "3306"
char chQuery[1024];
int statu=1;
int status=0;
MYSQL *Mconn;
char sql_query[256], sql_sub_query[50];
int i=0, res=0, conn_fail=0, conn_iter=0;
char response[50];// to go
vuser_init()
{
lr_load_dll("libmysql.dll");
//Mconn = lr_mysql_connect(MYSQLSERVER, MYSQLUSERNAME, MYSQLPASSWORD, MYSQLDB, atoi(MYSQLPORT));
lr_start_transaction("mysql_conn"); //设置一个连接数据库的事务
/*------------------------------------------------------------------------*/
/* Initialise MySQL */
if(!(Mconn = mysql_init(NULL)))
{
lr_message("Error -1: Cannot initialize MySQL - %s", mysql_error(Mconn));
//return -1;
statu = 0;
lr_end_transaction("mysql_conn", LR_FAIL); //初始化数据库失败判定事务失败
}
/*------------------------------------------------------------------------*/
do
{
/* Connect to database */
if (!mysql_real_connect(Mconn, MYSQLSERVER, MYSQLUSERNAME, MYSQLPASSWORD, MYSQLDB, atoi(MYSQLPORT), NULL, 0))
{
conn_fail = -2;
conn_iter++;
sleep(100);
}
else
conn_fail = 0;
}
while(conn_fail < 0 && conn_iter < 10);
if (conn_fail < 0)
{
lr_message("Error -2: %s", mysql_error(Mconn));
//mysql_close(Mconn);
//return -2;
statu = 0;
lr_end_transaction("mysql_conn", LR_FAIL); //连接数据库失败判定事务失败
}
else
{
//lr_message("MySql - Good Connection");
//mysql_close(Mconn);
statu = 1;
lr_end_transaction("mysql_conn", LR_PASS); //连接数据库成功,事务通过。
}
return 0;
}
Action()
{
if(statu){ //成功连接数据库后才进行执行sql的操作
lr_start_transaction("mysql_insert");
sprintf(chQuery, "INSERT INTO lr_test (username,password) VALUE("%s","%s")",lr_eval_string("{user}"),lr_eval_string("{pwd}"));
//sprintf(chQuery,"SELECT username,password FROM lr_test");
//sprintf(chQuery,"UPDATE lr_test SET password = "%s" WHERE username='tom'",lr_eval_string ("{pwd}"));
status = lr_mysql_query(Mconn, chQuery);
if(status!=0){ //判断sql是否执行成功
lr_end_transaction("mysql_insert",LR_FAIL );
}else{
lr_end_transaction("mysql_insert", LR_PASS);
}
}
return 0;
}
vuser_end()
{
lr_mysql_disconnect(Mconn); //关闭数据库连接
return 0;
}

以上是插入数据的操作,根据之前的介绍, 测试更新和查询,只需修改sql语句即可。剩下的就是将脚本加载到负载生成器中,进行各种场景的配置、测试即可。
各种测试场景运行完之后,就是分析图表的过程了,因为我们测试是针对执行sql语句设置的事务,即通过一个事务就成功的执行一句sql语句,那么事务的响应时间也就是执行sql所花的时间,可以取平均事务响应时间作为平均执行一句sql所花时间的度量。每秒事务数是在单位时间(秒)内执行sql的条数,作为执行sql语句速率的度量。
在运行测试场景时,尽量将运行时间设置长一些,这样采集到的数据越多,结果越准确。分别模拟不同的虚拟用户数来测试,不同的虚拟用户数在运行场景时,每秒事务数是不一样的,当达到一定的虚拟用户数后,每秒事务数会降低,或者出现错误,此时测试即可结束,取每秒事务数最大的一组数据作为测试结果。
以上就是loadrunner利用mysql lib库测试mysql数据库的一个大致过程。

参考资料

http://www.bish.co.uk/forum/index.php?topic=50.0
http://www.bish.co.uk/forum/index.php?topic=77.0

声明:本文为原创,作者为 归根落叶,转载时请保留本声明及附带文章链接:https://www.bstester.com/2013/12/mysql-database-performance-testing-using-loadrunner

----------------------------------------以下为本人代码备忘-------------------------------

init模块

#include "Ptt_MySQL.h"vuser_init()
{lr_load_dll ("libmysql.dll");#define MYSQLSERVER "localhost"#define MYSQLUSERNAME "root"#define MYSQLPASSWORD "root"#define MYSQLDB "wkcrm"#define MYSQLPORT "3306"return 0;
}

action块里面的代码


//Declare MySQL Elements
char sqQuery[512]; // The MySQL query to be executed #定义一个字符数组存储查询的sql语句
MYSQL *Mconn; // The MySQL connection string #mysql连接字符串
int MyRC; // The MySQL return code #mysql的返回码,可以判断sql语句是否执行成功。
Action()
{
//Create the connection string to connect to the server and relevant database
//  #创建一个连接字符串连接服务器和数据库
Mconn = lr_mysql_connect(MYSQLSERVER, MYSQLUSERNAME, MYSQLPASSWORD, MYSQLDB, atoi(MYSQLPORT));
//Build an SQL query and save the query as sqQuery #构建一个sql语句存储在sqQuery字符数组中
sprintf(sqQuery, "select leads_id from wkcrm_leads");
//Execute the SQL query (sqQuery) against the server and database defined as Mconn
//  #执行sql语句
lr_mysql_query(Mconn, sqQuery);
//Save the values returned in the first row of the table
// #查询的结果会存在一个表中,这里取出第一行的数据。
//N.B. The row/cell values appear to be the "wrong way round" #
// 注意,这里的行和列是颠倒的,相当于返回的数据表中一列数据表示数据库中表的一行数据。
lr_save_string(row[0][0].cell, "leads_id");
// lr_save_string(row[1][0].cell, "sPassword");
// lr_save_string(row[2][0].cell, "sSecret");
//Output the returned values #打印出查询出来的结果
lr_output_message(lr_eval_string("leads_id: {leads_id}"));
// lr_output_message(lr_eval_string("Password: {sPassword}"));
// lr_output_message(lr_eval_string("Secret: {sSecret}"));lr_mysql_disconnect(Mconn);//断开数据库连接
return 0;
}

发现以上方法只能连接本地数据库,远程数据库不知道什么原因,连接不了。

转载于:https://my.oschina.net/bysu/blog/776521

运用Loadrunner测试Mysql数据库性能相关推荐

  1. loadrunner mysql性能测试_运用Loadrunner测试Mysql数据库性能 TRON•极客

    1.前言 针对数据库的性能测试,loadrunner本身支持sql server和oracle数据库,这两种数据库可以用loadrunner直接录制进行测试.而我们项目中使用的是mysql数据库,针对 ...

  2. 使用数据库的压测工具super-smack测试mysql数据库性能

    一.下载 super-smack 下载地址:http://vegan.net/tony/supersmack/ 源码:http://vegan.net/tony/supersmack/super-sm ...

  3. sysbench 1.0.6 mysql_Sysbench 测试mysql数据库性能(version:sysbench-1.1.0)

    继上面安装完Mysql rpm 安装之后需要用sysbench对数据库进行性能测试: 下载 git clone https://github.com/akopytov/sysbench.git 或者直 ...

  4. CentOS7.x Sysbench 测试mysql数据库性能(version:sysbench-1.1.0)

    前言: 什么是sysbench? Oracle官方也使用该工具对MySQL进行测试 根据互联网应用特点进行测试 可以根据某个具体操作进行测试 还支持Oracle.PostgreSQL的测试 1.1.0 ...

  5. LoadRunner 测试Oracle数据库及Siebel性能

    本次测试使用的loadrunner 版本为8.1,oracle数据库版本为10.2.0.1,各版本的测试方法基本是一样的.这里提供loadrunner 8.1,10000个web用户的license: ...

  6. 教程,使用YCSB测试MYSQL数据库,获取千万条测试后的数据

    Yahoo! Cloud Serving Benchmark (YCSB)是一个数据库特别是nosql数据库性能测试的benchmark.在GitHub中有3.9千个star和1.9千个forks.本 ...

  7. mysql 改表面_MySQL_解析MySQL数据库性能优化的六大技巧,数据库表表面上存在索引和防 - phpStudy...

    解析MySQL数据库性能优化的六大技巧 数据库表表面上存在索引和防错机制,然而一个简单的查询就会耗费很长时间.Web应用程序或许在开发环境中运行良好,但在产品环境中表现同样糟糕.如果你是个数据库管理员 ...

  8. linux mysql数据库优化_MySQL_Linux下MySQL数据库性能调优方法,以下的环境具备一定的代表性 - phpStudy...

    Linux下MySQL数据库性能调优方法 以下的环境具备一定的代表性,可以说是中小企业一般配置和工作环境.希望通过本文能让大家理解Linux下MySQL数据库性能调优方法. 硬件准备环境: 硬盘: 1 ...

  9. mysql jdbc 绑定变量_jdbc测试mysql数据库sql预解析(绑定变量)

    jdbc测试mysql数据库sql预解析(绑定变量) 用习惯了oracle,学习mysql,想测试一下mysql绑定变量的效果.以前看网上介绍大部份都说mysql没有sql共享池的概念,所以也不存在s ...

最新文章

  1. HTML中nbsp; ensp; emsp; thinsp;等6种空白空格的区别
  2. 成功解决matplotlib绘图的时候横坐标或纵坐标文本显示不全/显示一半/显示不完整的问题
  3. JAVA 串口编程 (一)
  4. 设计制作简单计算机,自己设计制作CPU与单片机
  5. Dojo QuickStart 快速入门教程 (2) 基本框架
  6. 在JVM上对高并发HTTP服务器进行基准测试
  7. mnist数据集svm python_python支持向量机分类MNIST数据集
  8. 【Gitlab+Jenkins+Ansible】构建自动化部署
  9. cloc统计想项目行数
  10. 解决Python包下载慢问题
  11. 有道智云OCR图片识别文字+返回数据处理技巧(实现语言-按键精灵脚本请求识别+java服务端处理数据)...
  12. win10 网络发现 打开保存后,自动关闭
  13. c语言编译bss和data,.bss段和.data段的区别
  14. 路由2台,二层交换机4台,三层1台,实现网络互联
  15. db是哪个城市的缩写_全国所有城市拼音及缩写
  16. 如何计算机械能增加量,探讨优化验证机械能守恒定律实验中动能增加量的计算方法...
  17. 违背妇女意志_2018年国际妇女节:在技术中庆祝妇女
  18. vue使用vue-dplayer播放m3u8视频
  19. 机器学习的最佳入门学习资源
  20. linux防火墙删除ip白名单命令,利用CentOS系统IPtables防火墙添加网站IP白名单

热门文章

  1. 关于window.showModalDialog()返回值的学习
  2. oracle 时间戳生成语句(秒级+毫秒级)
  3. ScrollView详解
  4. socket服务端处理多个客户端的请求学习理解
  5. 关于Sa系列用户不能登录,只能本地windows身份验证的说明
  6. Stella 知识库--模型类的设计
  7. oracle和db2之间的基本差别
  8. 读后感-论文Patch-based Convolutional Neural Network for Whole Slide Tissue Image Classification
  9. MySQL8.0.11的安装和Navicat连接mysql
  10. activemq高可用