Tpcc-MySQL测试详解
前言:
TPC-C规范概要
TPC-C是专门针对联机交易处理系统(OLTP系统)的,一般情况下我们也把这类系统称为业务处理系统。
TPC-C测试规范中模拟了一个比较复杂并具有代表意义的OLTP应用环境:
假设有一个大型商品批发商,它拥有若干个分布在不同区域的商品库;每个仓库负责为10个销售点供货;每个销售点为3000个客户提供服务;每个客户平均一个订单有10项产品;所有订单中约1%的产品在其直接所属的仓库中没有存货,需要由其他区域的仓库来供货。同时,每个仓库都要维护公司销售的100000种商品的库存记录。
该系统需要处理的交易为以下几种:
New-Order:客户输入一笔新的订货交易;
Payment:更新客户账户余额以反映其支付状况;
Delivery:发货(模拟批处理交易);
Order-Status:查询客户最近交易的状态;
Stock-Level:查询仓库库存状况,以便能够及时补货。
对于前四种类型的交易,要求响应时间在5秒以内;对于库存状况查询交易,要求响应时间在20秒以内。
TPC-C测试指标
TPC-C测试的结果主要有两个指标,即流量指标(Throughput,简称tpmC)和性价比(Price/Performance,简称Price/tpmC)。
流量指标(Throughput,简称tpmC):按照TPC组织的定义,流量指标描述了系统在执行支付操作、订单状态查询、发货和库存状态查询这4种交易的同时,每分钟可以处理多少个新订单交易。所有交易的响应时间必须满足TPC-C测试规范的要求,且各种交易数量所占的比例也应该满足TPC-C测试规范的要求。在这种情况下,流量指标值越大说明系统的联机事务处理能力越高。
性价比(Price/Performance,简称Price/tpmc):即测试系统的整体价格与流量指标的比值,在获得相同的tpmC值的情况下,价格越低越好。
一、安装
1、mysql8.0安装
参考其他博文
2、tpcc-mysql安装
yum -y install bzr .
bzr branch lp:~percona-dev/perconatools/tpcc-mysql
cd tpcc-mysql/src
make
#然后会在上层目录生成 tpcc_load tpcc_start两个二进制程序。
在 tpcc-mysql文件中生成了tpcc_load及tpcc_start 文件,即表示tpcc完成安装
不建议下载 tpcc-mysql-master.zip 的源码包,当时找了好多源,安装后出问题,并且会sc=0的调不到数据的情况
二、使用
1、导表
1)、数据库中创建数据库
数据库名任意
2)、导入数据表
mysql -uroot -p123456 tpcc <./create_table.sql # tpcc是数据库名,可以任意起
mysql -uroot -p123456 tpcc <./add_fkey_idx.sql # 导入外键
2、建模 #指创建仓库
# ./tpcc_load -h localhost -d tpcc -u root -p "123456" -w 5
命令格式:
tpcc_load -h server_host -P port -d database_name -u mysql_user -p mysql_password -w warehouses -l part -m min_wh -n max_wh
./tpcc_load --halp 查看帮助 #有的版本不需要加参数,建议使用之前先 --help
参数含义:
-h server_host: 服务器名 或 IP地址
-P port : 端口号,默认为3306 #可省略
-d database_name: 数据库名
-u mysql_user : 用户名
-p mysql_password : 密码
-w warehouses: 仓库的数量
选项warehouse意为指定测试库下的仓库数量
选项[part]为只创建数据到[part]对应的表中 # 可省略
选项[min_wh]、[max_wh]为min_wid max_wid # 可省略
真实测试场景中,仓库数一般不建议少于100个,视服务器硬件配置而定,如果是配备了SSD或者PCIE SSD这种高IOPS设备的话,建议最少不低于1000个。
3、测试
# ./tpcc_start -hlocalhost -d tpcc -u root -p "123456" -w 5 -c 5 -r 120 -l 300 > tpcc-output-log
命令格式:
tpcc_start -h server_host -P port -d database_name -u mysql_user -p mysql_password -w warehouses -c connections -r warmup_time -l running_time -me report_interval -f report_file
# ./tpcc_start --halp 查看帮助
参数含义
-h server_host: 服务器名
-P port : 端口号,默认为3306
-d database_name: 数据库名
-u mysql_user : 用户名
-p mysql_password : 密码
-w warehouses: 仓库的数量
-c connections : 线程数,默认为1
-r warmup_time : 热身时间,单位:s,默认为10s ,热身是为了将数据加载到内存。
-l running_time: 测试时间,单位:s,默认为20s
-i report_interval: 指定生成报告间隔时长
-f report_file: 测试结果输出文件
现在我们来开启一个测试案例:
./tpcc_start -h localhost -d tpcc1000 -u tpcc_user -p "tpcc_password" -w 1000 -c 32 -r 120 -l 3600 -f tpcc_mysql_20140921.log >> tpcc_caseX_20140921.log 2>&1
即:模拟 1000个仓库规模,并发 16个线程进行测试,热身时间为 60秒, 压测时间为 1小时。
真实测试场景中,建议预热时间不小于5分钟,持续压测时长不小于30分钟,否则测试数据可能不具参考意义;
查看进程: cat /proc/cupinfo
4、测试结果分析
1)、发起测试
./tpcc_start -h 1.2.3.4 -P 3306 -d tpcc10 -u tpcc -p tpcc -w 10 -c 64 -r 30 -l 120 -f tpcclog_201409211538_64_THREADS.log >> tpcc_noaid_2_20140921_64.log 2>&1
2)、测试结果输出如下:
-- 本轮tpcc压测的一些基本信息
###easy### TPC-C Load Generator
option h wif value '1.2.3.4' -- 主机
option P wif value '3306' -- 端口
option d wif value 'tpcc10' -- 数据库
option u wif value 'tpcc' -- 账号
option p wif value 'tpcc' -- 密码
option w wif value '10' -- 仓库数
option c wif value '64' -- 并发线程数
option r wif value '30' -- 数据预热时长
option l wif value '120' -- 压测时长
option f wif value 'tpcclog_20140921_64_THREADS.res' -- 输出报告日志文件
RAMP-UP TIME.(30 sec.)
-- 预热结束,开始进行压测
MEASURING START.
-- 每10秒钟输出一次压测数据
10, 8376(0):2.744|3.211, 8374(0):0.523|1.626, 838(0):0.250|0.305, 837(0):3.241|3.518, 839(0):9.086|10.676
20, 8294(0):2.175|2.327, 8292(0):0.420|0.495, 829(0):0.206|0.243, 827(0):2.489|2.593, 827(0):7.214|7.646
…
110, 8800(0):2.149|2.458, 8792(0):0.424|0.710, 879(0):0.207|0.244, 878(0):2.461|2.556, 878(0):7.042|7.341
120, 8819(0):2.147|2.327, 8820(0):0.424|0.568, 882(0):0.208|0.237, 881(0):2.483|2.561, 883(0):7.025|7.405
解释
-- 以逗号分隔,共6列
-- 第一列,第N次10秒
-- 第二列,新订单成功执行压测的次数【8376】(推迟执行压测的次数【0】) : 90%事务的响应时间|本轮测试最大响应时间【2.744】| 新订单事务数也被认为是总有效事务数的指标【3.211】
-- 第三列,支付业务成功执行次数(推迟执行次数) : 90%事务的响应时间 | 本轮测试最大响应时间
-- 第四列,订单状态业务的结果,后面几个的意义同上
-- 第五列,物流发货业务的结果,后面几个的意义同上
-- 第六列,库存仓储业务的结果,后面几个的意义同上
-- 压测结束
STOPPING THREADS................................................................
(success,简写sc)次数,延迟(late,简写lt)次数,重试(retry,简写rt)次数,失败(failure,简写fl)次数
-- 第一次结果统计
[0] sc:100589 lt:0 rt:0 fl:0 -- New-Order,新订单业务成功
[1] sc:100552 lt:0 rt:0 fl:0 -- Payment,支付业务统计,其他同上
[2] sc:10059 lt:0 rt:0 fl:0 -- Order-Status,订单状态业务统计,其他同上
[3] sc:10057 lt:0 rt:0 fl:0 -- Delivery,发货业务统计,其他同上
[4] sc:10058 lt:0 rt:0 fl:0 -- Stock-Level,库存业务统计,其他同上
in 120 sec.
-- 第二次统计结果,其他同上
[0] sc:100590 lt:0 rt:0 fl:0
[1] sc:100582 lt:0 rt:0 fl:0
[2] sc:10059 lt:0 rt:0 fl:0
[3] sc:10057 lt:0 rt:0 fl:0
[4] sc:10059 lt:0 rt:0 fl:0
(all must be [OK]) -- 下面所有业务逻辑结果都必须为 OK 才行
[transaction percentage]
Payment: 43.47% (>=43.0%) [OK] -- 支付成功次数(上述统计结果中 sc + lt)必须大于43.0%,否则结果为NG,而不是OK
Order-Status: 4.35% (>= 4.0%) [OK] -- 订单状态,其他同上
Delivery: 4.35% (>= 4.0%) [OK] -- 发货,其他同上
Stock-Level: 4.35% (>= 4.0%) [OK] -- 库存,其他同上
[response time (at least 90% passed)] -- 响应耗时指标必须超过90%通过才行
New-Order: 100.00% [OK] -- 下面几个响应耗时指标全部 100% 通过
Payment: 100.00% [OK]
Order-Status: 100.00% [OK]
Delivery: 100.00% [OK]
Stock-Level: 100.00% [OK]
50294.500 TpmC -- TpmC结果值(每分钟事务数,该值是第一次统计结果中的新订单事务数除以总耗时分钟数,例如本例中是:100589/2 = 50294.500)
5、生成图片
待补充
错误信息汇总:
1、 进行 ./tpcc_start -h localhost -d tpcc1000 -u tpcc_user -p "tpcc_password" -w 1000 -c 32 -r 120 -l 3600 -f tpcc_mysql_20140921.log 报错
2002, HY000. Can't connect to local MySQL server through socket Vvar. run/mysqld/mysqld.sock'
原因:
tpcc-mysql存在2个bug,需要手动修改
文件1: main.c
源信息:
char db_socket[DB_STRING_MAX] = " ";
if(is_local==1){
/ exec sql connect :connect_string; /
resp = mysql_real_connect(ctx[t_num], "localhost", db_user, db_password, db_string_full, port, db_socket, 0);
}else{
/ exec sql connect :connect_string USING :db_string; /
resp = mysql_real_connect(ctx[t_num], connect_string, db_user, db_password, db_string_full, port, db_socket, 0);
}
修改方法一:
在char db_socket[DB_STRING_MAX] = " ",中写入mysql.sock路径,并在每个语句前加上 mysql_thread_init();
完整语句:
char db_socket[DB_STRING_MAX] = "/var/lib/mysql/mysql.sock";
if(is_local==1){
/ exec sql connect :connect_string; /
mysql_thread_init();
resp = mysql_real_connect(ctx[t_num], "localhost", db_user, db_password, db_string_full, port, db_socket, 0);
}else{
/ exec sql connect :connect_string USING :db_string; /
mysql_thread_init();
resp = mysql_real_connect(ctx[t_num], connect_string, db_user, db_password, db_string_full, port, db_socket, 0);
}
修改方法二:
直接替换db_socket 为 "/var/lib/mysql/mysql.sock"
完整语句:
char db_socket[DB_STRING_MAX] = " ";
if(is_local==1){
/ exec sql connect :connect_string; /
mysql_thread_init();
resp = mysql_real_connect(ctx[t_num], "localhost", db_user, db_password, db_string_full, port, "/var/lib/mysql/mysql.sock", 0);
}else{
/ exec sql connect :connect_string USING :db_string; /
mysql_thread_init();
resp = mysql_real_connect(ctx[t_num], connect_string, db_user, db_password, db_string_full, "/var/lib/mysql/mysql.sock", 0);
}
文件二:load.c
源文件:
if(is_local==1){
/* exec sql connect :connect_string; */
resp = mysql_real_connect(mysql, "localhost", db_user, db_password, db_string, port, NULL, 0);
}else{
/* exec sql connect :connect_string USING :db_string; */
resp = mysql_real_connect(mysql, connect_string, db_user, db_password, db_string, port, NULL, 0);
修改方法:
将语句中的 NULL替换为 "/var/lib/mysql/mysql.sock",并在每个语句前加上 mysql_thread_init();
完整语句:
if(is_local==1){
/* exec sql connect :connect_string; */
mysql_thread_init();
resp = mysql_real_connect(mysql, "localhost", db_user, db_password, db_string, port, "/var/lib/mysql/mysql.sock", 0);
}else{
/* exec sql connect :connect_string USING :db_string; */
mysql_thread_init();
resp = mysql_real_connect(mysql, connect_string, db_user, db_password, db_string, port, "/var/lib/mysql/mysql.sock", 0);
2、tpcc_mysql找不到 mysql.sock文件
tpcc 默认会读取 /var/lib/mysql/mysql.sock 这个socket 文件,如果你的 socket 文件不在相应路径的话,可以使用ln -s命令做个软连接
资料来源:https://mp.weixin.qq.com/s/Kv1rk6ybehbw8vBfPyxNsw
https://blog.csdn.net/sincoqiu/article/details/70226268
https://blog.csdn.net/jswangchang/article/details/81317741 (生成图片)
https://www.cnblogs.com/bulh/articles/11229473.html