|
| 1 | +#!/bin/sh |
| 2 | +#by ljk 20161003 |
| 3 | + |
| 4 | +#通过sysbench测试mysql相关性能,并将关键数据存储于‘test.sysbenc_test’表中 |
| 5 | + |
| 6 | +#定义记录测试结果的mysql连接相关参数,本例我在测试机上记录测试结果 |
| 7 | +m_user='test' |
| 8 | +m_passwd='test' |
| 9 | +m_port='3307' |
| 10 | +m_host='127.0.0.1' |
| 11 | + |
| 12 | +#定义错误日志文件 |
| 13 | +log=/tmp/mysql_oltp.log |
| 14 | +#定义测试线程 |
| 15 | +threds_num='8 24 48 64 96 128 160 196 256' |
| 16 | + |
| 17 | +#测试函数 |
| 18 | +sb_test() { |
| 19 | + |
| 20 | + #定义测试方式相关变量 |
| 21 | + tables_count=16 #测试表的数量 |
| 22 | + if [ "$3" == "read-only" ];then read_only='on';else read_only='off';fi #根据脚本参数确定是否read-only |
| 23 | + |
| 24 | + #创建记录测试信息的表 |
| 25 | + echo -e "\n---------------\n创建测测试结果表test.sysbench_test\n---------------" |
| 26 | + mysql -u$m_user -p$m_passwd -P$m_port -h$m_host <<EOF |
| 27 | + CREATE TABLE IF NOT EXISTS test.sysbench_test ( |
| 28 | + scenario varchar(30) NOT NULL DEFAULT '' COMMENT '测试场景', |
| 29 | + server_name varchar(15) NOT NULL COMMENT '被测DB name', |
| 30 | + test_type varchar(15) NOT NULL COMMENT 'read-only,read-write,insert等', |
| 31 | + sb_threads int(11) NOT NULL DEFAULT '0' COMMENT 'sysbench 测试线程', |
| 32 | + server_load decimal(12,2) NOT NULL DEFAULT '0.00' COMMENT '以当前线程测试完后立刻记录一分钟负载值', |
| 33 | + request_total int(11) NOT NULL DEFAULT '0', |
| 34 | + request_read int(11) NOT NULL DEFAULT '0', |
| 35 | + request_write int(11) NOT NULL DEFAULT '0', |
| 36 | + request_per_second decimal(12,2) NOT NULL DEFAULT '0.00', |
| 37 | + total_time decimal(12,2) NOT NULL DEFAULT '0.00' COMMENT '单位秒', |
| 38 | + 95_pct_time decimal(12,2) NOT NULL DEFAULT '0.00' COMMENT '单位毫秒' |
| 39 | + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
| 40 | +EOF |
| 41 | + if [ $? -ne 0 ];then exit -1;fi |
| 42 | + |
| 43 | + #开始测试,每种条件测3次,分析时取平均值 |
| 44 | + echo -e "\n---------------\n场景:$2 模式:$3\n---------------" |
| 45 | + for i in {1..3};do |
| 46 | + |
| 47 | + for sb_threds in $threds_num;do #按照指定的sysbench线程测试 |
| 48 | + printf " %-10s %s\n" $sb_threds线程 第$i次运行... |
| 49 | + |
| 50 | + #result 作为每次最小测试单元的结果,根据sysbench测试结果各参数的出现顺序,以request_read、request_write、request_total、request_per_second、total_time、95_pct_time为顺序插入表中。下条命令中,egerp之后的操作是为了对sysbench的输出做筛选和格式化,以便插入数据库 |
| 51 | + sysbench --test=/usr/share/doc/sysbench/tests/db/oltp.lua --mysql-user=$6 --mysql-password=$7 --mysql-port=$5 --mysql-host=$4 --num-threads=$sb_threds run --oltp-skip-trx=on --oltp-read-only=$read_only > $log |
| 52 | + if [ $? -ne 0 ];then |
| 53 | + echo -e "\nSysbench error! For more information see $log" |
| 54 | + exit -1 |
| 55 | + fi |
| 56 | + result=$(cat $log | egrep "read:|write:|read/write.*:|total:|total\ time:|approx\..*95.*:" |sed -r -e "s/[0-9]+ \(//g" -e "s/\ per sec\.\)//g" -e "s/m?s$//g" | awk '{printf("%s ",$NF)}'|sed "s/\ /,/g" | sed "s/,$//g") |
| 57 | + |
| 58 | + #测试完成后立刻记录系统一分钟负载值,可近似认为测试过程中proxy的负载抽样 |
| 59 | + load=$(ssh -p22 $4 "uptime|awk -F: '{print \$NF}'|awk -F, '{print \$1}'" 2>/dev/null) |
| 60 | + |
| 61 | + #本次测试结果写入数据库 |
| 62 | + mysql -u$m_user -p$m_passwd -P$m_port -h$m_host <<EOF 2> $log |
| 63 | + INSERT INTO test.sysbench_test (scenario,server_name,test_type,sb_threads,server_load,request_read,request_write,request_total,request_per_second,total_time,95_pct_time) |
| 64 | + VALUES ('$2','$4','$3','$sb_threds','$load',$result); |
| 65 | +EOF |
| 66 | + |
| 67 | + if [ $? -ne 0 ];then |
| 68 | + echo -e "\n----------$sb_threds线程测试,第$i次插入数据库时失败----------" |
| 69 | + echo "INSERT VALUES ('$2','$4','$3',$sb_threds,$load,$result)" |
| 70 | + exit -2 |
| 71 | + fi |
| 72 | + sleep 60 #让库歇一会,也让一分钟负载能够恢复到测试前的值 |
| 73 | + done |
| 74 | + |
| 75 | + done |
| 76 | +} |
| 77 | + |
| 78 | +#结果分析函数 |
| 79 | +sb_analyse() { |
| 80 | + mysql -u$m_user -p$m_passwd -h$m_host -P$m_port <<EOF 2> $log |
| 81 | + SELECT |
| 82 | + scenario, |
| 83 | + server_name, |
| 84 | + test_type, |
| 85 | + sb_threads, |
| 86 | + convert(avg(server_load),decimal(12,2)) as server_load, |
| 87 | + convert(avg(request_total),decimal(12,0)) as request_total, |
| 88 | + convert(avg(request_read),decimal(12,0)) as request_read, |
| 89 | + convert(avg(request_write),decimal(12,0)) as request_write, |
| 90 | + convert(avg(request_per_second),decimal(12,2)) as request_per_second, |
| 91 | + convert(avg(total_time),decimal(12,2)) as total_time, |
| 92 | + convert(avg(95_pct_time),decimal(12,2)) as 95_pct_time |
| 93 | + FROM test.sysbench_test group by scenario,server_name,test_type,sb_threads |
| 94 | +EOF |
| 95 | +} |
| 96 | + |
| 97 | +#画图函数 |
| 98 | +sb_chart() { |
| 99 | + sb_analyse > /tmp/mysql_oltp.dat |
| 100 | + |
| 101 | + for chart_type in "request_per_second" "total_time" "95_pct_time";do #这里写死了关注的三个指标,也就是会画三张图 |
| 102 | + |
| 103 | + col_num=0 #该行及下面这个for循环用于取得三个指标在数据中的列号 |
| 104 | + for col_name in `cat /tmp/aualyse.txt |awk 'NR<2 {print}'`;do |
| 105 | + let col_num++ |
| 106 | + if [ $col_name == $chart_type ];then break;fi |
| 107 | + done |
| 108 | + |
| 109 | + if [ $chart_type == "request_per_second" ];then #根据图表特点为不同的chart_type设置不同的key position |
| 110 | + key_pos="bottom right" |
| 111 | + unit="" |
| 112 | + elif [ $chart_type == "total_time" ];then |
| 113 | + key_pos="top right" |
| 114 | + unit="(s)" |
| 115 | + elif [ $chart_type == "95_pct_time" ];then |
| 116 | + key_pos="top left" |
| 117 | + unit="(ms)" |
| 118 | + fi |
| 119 | + |
| 120 | + plot_cmd="set term png size 800,600;set output '/tmp/$chart_type.png';set title '$chart_type $unit';set grid;set key $key_pos;plot " |
| 121 | + |
| 122 | + if [ $# -eq 0 ];then |
| 123 | + #对分析结果中所有场景进行画图 |
| 124 | + for scenario in `mysql -u$m_user -p$m_passwd -h$m_host -P$m_port -s -e "select distinct(scenario) from test.sysbench_test" 2>/dev/null`;do |
| 125 | + sb_analyse | awk -v scenario=$scenario '$1 == scenario {print}' > /tmp/"$scenario.dat" |
| 126 | + plot_cmd=${plot_cmd}"'/tmp/"$scenario.dat"' using $col_num:xtic(4) title '$scenario' with linespoints lw 2," |
| 127 | + done |
| 128 | + plot_cmd=$(echo $plot_cmd | sed 's/,$//g') |
| 129 | + echo $plot_cmd | gnuplot |
| 130 | + else |
| 131 | + #只绘制指定的场景 |
| 132 | + for scenario in $*;do |
| 133 | + sb_analyse | awk -v scenario=$scenario '$1 == scenario {print}' > /tmp/"$scenario.dat" |
| 134 | + plot_cmd=${plot_cmd}"'/tmp/"$scenario.dat"' using $col_num:xtic(4) title '$scenario' with linespoints lw 2," |
| 135 | + done |
| 136 | + plot_cmd=$(echo $plot_cmd | sed 's/,$//g') |
| 137 | + echo "$plot_cmd" | gnuplot |
| 138 | + fi |
| 139 | + done |
| 140 | +} |
| 141 | + |
| 142 | +#脚本使用说明/参数判断 |
| 143 | +if [ $# -eq 1 ] && [ $1 == "-h" -o $1 == "--help" ];then |
| 144 | + echo -e "\nUsage: $0 {test test_scenario test_type mysql_host mysql_port mysql_user mysql_password} | {analyse} | {chart [scenario]...}\n" |
| 145 | + echo ---------- |
| 146 | + echo -e "测试: 请在脚本后跟上 test test_scenario test_type mysql_host mysql_port mysql_user mysql_password 7个参数 !" |
| 147 | + echo -e " test_type: read-only 或 read-write, 表示测试模式" |
| 148 | + echo -e " 其余4参数表示待测试MySQL连接相关信息,密码若包含特殊字符,将其置于单引号内" |
| 149 | + echo -e "----------" |
| 150 | + echo -e "分析: 请在脚本后跟上 analyse" |
| 151 | + echo -e "----------" |
| 152 | + echo -e "画图: 请在脚本后面跟上" |
| 153 | + echo -e " 会在/tmp/下生成request_per_second.png total_time.png 95_pct_time.png 三张图" |
| 154 | + echo -e " chart (对分析结果中的所有测试场景画图)" |
| 155 | + echo -e " chart scenario ... (对指定的测试场景画图,场景名可查看analyse)\n" |
| 156 | + exit -1 |
| 157 | +elif [ "$1" == "test" -a $# -eq 7 ];then |
| 158 | + sb_test $1 $2 $3 $4 $5 $6 $7 |
| 159 | +elif [ "$1" == "analyse" -a $# -eq 1 ];then |
| 160 | + sb_analyse |
| 161 | +elif [ "$1" == "chart" ];then |
| 162 | + #chart函数可不接参数,也可接任意个'测试场景'作为参数 |
| 163 | + arg=($*) |
| 164 | + arg_len=${#arg[@]} |
| 165 | + sb_chart ${arg[@]:1:$arg_len-1} |
| 166 | +else |
| 167 | + echo -e "\nUsage: $0 {test test_scenario test_type mysql_host mysql_port mysql_user mysql_password} | {analyse} | {chart [scenario]...}\n" |
| 168 | +fi |
0 commit comments