因为在Loadrunner中没有MySQL协议,故无法直接采用MySQL协议来录制测试MySQL的脚本。目前用的比较多的方法有两种,一种是使用ODBC的方式来录制MySQL脚本,但流程过于复杂,限制较多;一种是直接在Loadrunner中通过C Vuser类型协议,调用MySQL的中的libmysql.dll进行MySQL脚本的编写。此处,我们选择后者进行脚本的编写。
(1)安装mysql
下载mysql的服务器/客户端安装包并安装,mysql的版本最好跟被测的mysql数据库服务器的版本一致,安装的时候,按照默认选项一直点下一步就行了。
安装mysql的目的主要是为了获libmysql.dll动态库,因为libmysql.dll不仅是mysql中一个非常重要的动态链接库,还是我们接下来编写mysql脚本必须引用的。如果可以从被测mysql服务器端获取该libmysql.dll动态库,也可以不再安装mysql。
(2)在Lodrunner中新建C Vuser类型脚本
此处我们使用的是Loadrunner11。打开VUGen,新建C Vuser类型脚本。
C Vuser类型脚本实际上就是C语言类型的脚本,是无法进行录制的,只能自己根据实际业务的需要编写。
(3)附加libmysql.dll动态链接库
在VUGen中,选择File-->Add Files to Script,将libmysql.dll附加到脚本中。将libmysql.dll附加到脚本中,就可以直接使用libmysql.dll里的函数了,而且脚本还直接可以移植到别的电脑上使用,不再受libmysql.dll所在的位置限制。因为有些人附加libmysql.dll动态库采用绝对路径进行的,当libmysql.dll所在的位置变化时,还要相应的调整libmysql.dll所在绝对路径。
libmysql.dll动态链接库提供了很多函数来对数据库进行操作,大致可以分为以下几类:
第一部分 控制类函数
mysql_init()初始化MySQL对象
mysql_options()设置连接选项
mysql_real_connect()连接到MySQL数据库
mysql_real_escape_string()将查询串合法化
mysql_query()发出一个以空字符结束的查询串
mysql_real_query()发出一个查询串
mysql_store_result()一次性传送结果
mysql_use_result()逐行传送结果
mysql_free_result()释放结果集
mysql_change_user()改变用户
mysql_select_db()改变默认数据库
mysql_debug()送出调试信息
mysql_dump_debug_info()转储调试信息
mysql_ping()测试数据库是否处于活动状态
mysql_shutdown()请求数据库SHUTDOWN
mysql_close()关闭数据库连接
第二部分 信息获取类函数
mysql_character_set_name()获取默认字符集
mysql_get_client_info()获取客户端信息
mysql_host_info()获取主机信息
mysql_get_proto_info()获取协议信息
mysql_get_server_info()获取服务器信息
mysql_info()获取部分查询语句的附加信息
mysql_stat()获取数据库状态
mysql_list_dbs()获取数据库列表
mysql_list_tables()获取数据表列表
mysql_list_fields()获取字段列表
第三部分 行列类操作函数
mysql_field_count()获取字段数
mysql_affected_rows()获取受影响的行数
mysql_insert_id()获取AUTO_INCREMENT列的ID值
mysql_num_fields()获取结果集中的字段数
mysql_field_tell()获取当前字段位置
mysql_field_seek()定位字段
mysql_fetch_field()获取当前字段
mysql_fetch_field_direct()获取指定字段
mysql_frtch_fields()获取所有字段的数组
mysql_num_rows()获取行数
mysql_fetch_lengths()获取行长度
mysql_row_tell()获取当前行位置
mysql_row_seek()行定位
mysql_da ta_seek()行定位
mysql_fetch_row()获取当前行
第四部分 线程类操作函数
mysql_list_processes()返回所有线程列表
mysql_thread_id()获取当前线程ID
mysql_thread_safe()是否支持线程方式
mysql_kill()杀列一个线程
第五部分 出错处理类函数
mysql_errno()获取错误号
mysql_error()获取错误信息
第六部分 已过时的函数
mysql_connect()
mysql_create_db()
mysql_drop_db()
mysql_eof()
mysql_reload()
mysql_escape_string()
如果要看函数的具体参数和使用方法也可以参考与libmysql.dll对于的头文件mysql.h,可以在mysql的安装路径下搜索。头文件里面对每个函数的用途以及每隔参数的含义都有详细的说明。此外,在网上找别人写的例子,参考别人使用的代码也是了解动态库中函数的使用方法的一种途径,如http://blog.csdn.net/java2000_net/article/details/4324964。
(5)编写脚本
下面的脚本是针对mysql某个表的写入性能测试的编写的,此处模拟的业务流程是并发登录mysql数据库,然后一直往数据库中写入数据,写入100万条后,退出数据库的登录。测试的目标是找到该数据库中某个表写入记录数的瓶颈点。为了达到这个效果,此处将数据库登录的脚本放在在了Vuser_init模块中,将写入数据库的脚本放在了Action模块中,将退出数据库登录的脚本放在了Vuser_end模块中。
Vuser_init:
int rc; int db_connection; //数据库连接 int query_result; // 查询结果集 MYSQL_RES char** result_row; // 查询的数据行 char *server = "172.31.27.xx"; char *user = "user"; char *password = "password"; char *database = "ucenter"; int port = 3306; int unix_socket = NULL; int flags = 1; vuser_init() { // 找到libmysql.dll的所在位置.如果安装了mysql,并将dll文件导入了脚本内,可以直接load,不需要路径 rc = lr_load_dll("libmysql.dll"); if (rc != 0) { lr_error_message("Could not load libmysql.dll"); lr_abort(); } // 创建MySQL对象 db_connection = mysql_init(NULL); if (db_connection == NULL) { lr_error_message("Insufficient memory"); lr_abort(); } // 连接到MySQL数据库 rc = mysql_real_connect(db_connection, server, user, password, database, port, unix_socket, flags); if (rc == NULL) { lr_error_message("%s", mysql_error(db_connection)); mysql_close(db_connection); lr_abort(); } return 0; } |
Action:
Action() { // 向数据库插入数据,{NewParam_1}_{NewParam}是参数化之后的参数 lr_save_string (lr_eval_string("INSERT INTO ismxb_domainipicpstatus (service_code, datatype,ip,domain, servicetype, ipfp_status, icpstatus, license,organization, user_id, cur_time, scheme_status) VALUES ('56789', '1', '173.36.27.9','{NewParam_1}_{NewParam}', '24', NULL, '1', NULL, NULL, 'admin','2015-12-02 17:54:29', 1)") ,"paramInsertQuery"); rc = mysql_query(db_connection, lr_eval_string("{paramInsertQuery}")); if (rc!= 0) { lr_error_message("%s", mysql_error(db_connection)); mysql_close(db_connection); lr_abort(); } } |
Vuser_end:
vuser_end() { // 释放MySQL资源 mysql_close(db_connection);
return 0; } |