51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1946|回复: 2
打印 上一主题 下一主题

[转贴] 如何利用LoadRunner最高效的批量制造MySQL数据

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2017-7-17 14:42:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
批量制造数据的方法有很多种,也有许多专业的工具,但是都算不上高效,针对MySQL的批量插入数据,目前认为最高效的方式是通过执行Java代码(通过设置事务为非自动提交,以executeBatch批处理提交大量插入事务)来实现,但是JAVA的灵活参数化和大用户量分布式并发执行,绝对没有LoadRunner方便。
所以我们可以利用LoadRunner+JAVA的方式,来实现高效、高可靠、持续性的批量造数据,既利用LoadRunner的Java_Vuser:
1、在loadrunner中新建脚本(本文以LoadRunner11为例),要求选择协议类型为Java->Java Vuser
2、在Run-time Settings设置JDK路径,由于LoadRunner11不支持jdk1.8,所以推荐引用jdk1.6
3、需要mysql的java驱动,可以到MySQL官网下载"mysql-connector-Java",并通过Run-time Settings引用JAR包

4、在java Vuser输入以下样例代码:
  1. <font size="4">/*
  2. * LoadRunner Java script. (Build: _build_number_)
  3. *  
  4. * Script Description:  
  5. *                     
  6. */  
  7. import lrapi.lr;  
  8. import java.beans.Statement;   
  9. import java.sql.Connection;   
  10. import java.sql.DriverManager;   
  11. import java.sql.PreparedStatement;   
  12. import java.sql.ResultSet;   
  13. import java.sql.SQLException;   
  14.   
  15. public class Actions  
  16. {  
  17.     private Connection conn = null;   
  18.     PreparedStatement statement = null;  
  19.    
  20.     // connect to MySQL   
  21.     void connSQL() {   
  22.         String url = "jdbc:mysql://172.16.1.67:3306/test?characterEncoding=UTF-8";   
  23.         String username = "root";   
  24.         String password = "123456"; // 加载驱动程序以连接数据库     
  25.         try {     
  26.             Class.forName("com.mysql.jdbc.Driver" );     
  27.             conn = DriverManager.getConnection( url,username, password );     
  28.             }   
  29.         //捕获加载驱动程序异常   
  30.          catch ( ClassNotFoundException cnfex ) {   
  31.              System.err.println(   
  32.              "装载 JDBC/ODBC 驱动程序失败。" );   
  33.              cnfex.printStackTrace();     
  34.          }     
  35.          //捕获连接数据库异常   
  36.          catch ( SQLException sqlex ) {   
  37.              System.err.println( "无法连接数据库" );   
  38.              sqlex.printStackTrace();     
  39.          }   
  40.     }   
  41.    
  42.     // disconnect to MySQL   
  43.     void deconnSQL() {   
  44.         try {   
  45.             if (conn != null)   
  46.                 conn.close();   
  47.         } catch (Exception e) {   
  48.             System.out.println("关闭数据库问题 :");   
  49.             e.printStackTrace();   
  50.         }   
  51.     }   
  52.   
  53.     public int init() throws Throwable {  
  54.         connSQL();  
  55.         return 0;  
  56.     }//end of init  
  57.   
  58.   
  59.     public int action() throws Throwable {  
  60.         String sql = "insert into MySqlTest(ID, DataName, InsertTime, UpdateTime, DataType,DataSet) values(REPLACE(uuid(), '-', ''),?,now(),null,1,'LoadRunner')";  
  61.             conn.setAutoCommit(false);  
  62.         statement = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);  
  63.   
  64.         lr.start_transaction("Insert");  
  65.         for(int i=0;i<1000;i++){//每1000条记录为一组事务,每个虚拟用户至少执行一组批量插入事务  
  66.                 statement.setString(1,"Test-A2B-<RadParam>");//用LoadRunner的方式设置随机数参数  
  67.                 statement.addBatch();  
  68.         }  
  69.         statement.executeBatch();  
  70.             conn.commit();  
  71.   
  72.         lr.end_transaction("Insert", lr.AUTO);  
  73.         return 0;  
  74.     }//end of action  
  75.   
  76.   
  77.     public int end() throws Throwable {  
  78.         deconnSQL();  
  79.         return 0;  
  80.     }//end of end  
  81. }  </font>
复制代码
5、将以上脚本放到Loadrunner中执行(场景设置100用户,每个用户只执行一次,同时执行,这样就确保只插入10万条记录),经过测试,发现最多16秒就完成10万条记录的插入(平均执行的时间是11.658秒)。
7、也可以将for循环去掉,通过loadrunner的action循环1000次来实现

但是这样改变后速度要比用for循环慢多了,经过测试发现插入10万条数据,需要33秒(平均执行一次action是0.027秒),为什么呢,仔细对照就发现是因为action里包括了conn.commit(),也就是说每次循环都执行事务提交,批量1000条插入变成了单条插入。把脚本改动一下:
  1. <font size="4">public int init() throws Throwable {  
  2.     connSQL();  
  3.     String sql = "insert into MySqlTest(ID, DataName, InsertTime, UpdateTime, DataType,DataSet) values(REPLACE(uuid(), '-', ''),?,now(),null,1,'LoadRunner')";  
  4.     conn.setAutoCommit(false);  
  5.     statement = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);  
  6.     return 0;  
  7. }//end of init  
  8.   
  9. public int action() throws Throwable {      
  10.     lr.start_transaction("action");  
  11.   
  12.                statement.setString(1,"Test-A2B-<RadParam>");     
  13.                statement.addBatch();      
  14.   
  15.     lr.end_transaction("action", lr.AUTO);  
  16.     return 0;  
  17. }//end of action  
  18.   
  19. public int end() throws Throwable {  
  20.     statement.executeBatch();  
  21.     conn.commit();  
  22.     deconnSQL();  
  23.     return 0;  
  24. }//end of end  </font>
复制代码
这么一改动,就把prepareStatement和commit都放到循环action之外,相当于一个用户执行完1000条预插入记录后,才进行commit提交,速度立马提高,经过测试,10万条记录批量insert只要15秒(平均执行一次action是0.001秒)。
8、如果要插入更多的数据,只需要用更多的用户和执行更长的并发时间就能轻松实现,而且参数化方便,如果单台压力机承受不了,还可以分布式部署多台压力机。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

x
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-11-6 17:30 , Processed in 0.065780 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表