前言:
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測試指標
一、安裝
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' -- 輸出報告日志文件
[server]: 1.2.3.4
[port]: 3306
[DBname]: tpcc10
[user]: tpcc
[pass]: tpcc
[warehouse]: 10
[connection]: 64
[rampup]: 30 (sec.)
[measure]: 120 (sec.)
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 (生成圖片)
