數據庫壓力(瓶頸)評估!

背景:
    最近線上蠻重要的一個系統遇到了TCP連接瓶頸,運維由此陷入了焦頭爛額的工作中,筆者在公司負責維護和運維MySQL,領導也是擔心數據庫的瓶頸問題啊,筆者呢,也是好奇當前數據庫的瓶頸到底如何,所以,便誕生了本文,謹以此文記錄筆者對本地和測試環境進行壓測的結果。(建議同行讀者在讀完本文之後,在做測試,因爲上下相關)

工具選擇:
    1、mysqlslap
    2、sysbench

mysqlslap:


    1、使用系統自動生成的SQL腳本測試:
    mysqlslap --concurrency=50,100,200 --iterations=3 --number-int-cols=5 --number-char-cols=30 --auto-generate-sql --auto-generate-sql-add-autoincrement --auto-generate-sql-load-type=mixed --engine=myisam,innodb --number-of-queries=5000 --debug-info -uroot -p -S /home/data/mysql3306/mysql.sock

    concurrency:客戶端併發數量
    iterations:迭代次數(次數越多,取的平均值越準確)
    number-int-cols:代表示例表中integer類型有幾個
    auto-generate-sql:使用系統自動生成的SQL腳本
    auto-generate-sql-load-type:測試的類型是讀、寫、混合
    number-of-queries:總共查詢次數
    debug-info:輸出CPU及內存等信息

    2、使用自定義SQL測試:
    /usr/local/mysql/bin/mysqlslap --concurrency=700 --iterations=3 --create-schema=edusoho_e --query='SELECT * FROM biz_targetlog WHERE target_type="trade.paid_notify" LIMIT 1' --number-of-queries=2000 -uroot -p -S /home/data/mysql3306/mysql.sock
    Enter password:
    Benchmark
    Average number of seconds to run all queries: 0.341 seconds
    Minimum number of seconds to run all queries: 0.187 seconds
    Maximum number of seconds to run all queries: 0.607 seconds
    Number of clients running queries: 700
    Average number of queries per client: 2

    create-schema:使用自定義的測試庫
    query:自定義的語句

小結:
    mysqlslap是MySQL自帶的壓力測試工具,工具效果呢,只能說是仁者見仁,智者見智了!筆者在測試時,感覺此工具的Benchmark和系統load並不是成正比的,也就是說,相同的語句下(相同的迭代次數,相同的queries,相同的查詢語句,併發數大的(700)的Benchmark比並發數低的(600)的Benchmark還低,load也是;另外一方面,測試結果也是很不穩定,併發600的測試,第一次load>4,第二次相同的測試語句,load<1。
    不知道是什麼原因,筆者沒想明白,秉着實踐出真知的原則,感覺此工具測試結果不是很穩定,寫在這裏僅供瞭解一下

sysbench:

簡介:
    sysbench是一個模塊化的、跨平臺、多線程基準測試工具,主要用於評估測試各種不同系統參數下的數據庫負載情況,sysbench主要支持 MySQL,pgsql,oracle 這3種數據庫

安裝:
    yum install sysbench -y(筆者採用的是阿里雲yum源安裝,系統本地yum源好像沒有)
    [root@slave ~]#sysbench --version
    sysbench 1.0.17

測試用的lua腳本文件:
    [root@slave ~]#cd /usr/share/sysbench/
    [root@slave sysbench]# ls
    ... 根據名字都能明白測試用途
    筆者線上主要以SELECT爲主,所以將用oltp_read_only.lua腳本來做測試,讀者根據自己的情況自行選擇合適的腳本進行測試

Sysbench壓測MySQL流程:
prepare(準備數據) -> run(運行測試) -> cleanup(清除測試數據)


詳細用法:
[root@slave sysbench]# sysbench --help

準備數據:
以edusoho_e爲測試庫,生成10張表,每表5w數據
[root@slave sysbench]# sysbench oltp_read_only.lua --db-driver=mysql --mysql-user=root --mysql-password='' --mysql-socket=/home/data/mysql3306/mysql.sock --mysql-db=edusoho_e --tables=10 --table-size=50000 prepare
sysbench 1.0.17 (using system LuaJIT 2.0.4)

Initializing worker threads...

Creating table 'sbtest8'...
Creating table 'sbtest2'...
Creating table 'sbtest5'...
Creating table 'sbtest3'...
Creating table 'sbtest4'...
Creating table 'sbtest7'...
Creating table 'sbtest1'...
Creating table 'sbtest10'...
Creating table 'sbtest6'...
Creating table 'sbtest9'...
Inserting 50000 records into 'sbtest10'
Inserting 50000 records into 'sbtest3'
Inserting 50000 records into 'sbtest9'
Inserting 50000 records into 'sbtest4'
Inserting 50000 records into 'sbtest6'
Inserting 50000 records into 'sbtest5'
Inserting 50000 records into 'sbtest2'
Inserting 50000 records into 'sbtest1'
Inserting 50000 records into 'sbtest7'
Inserting 50000 records into 'sbtest8'
Creating a secondary index on 'sbtest4'...
Creating a secondary index on 'sbtest7'...
Creating a secondary index on 'sbtest2'...
Creating a secondary index on 'sbtest5'...
Creating a secondary index on 'sbtest9'...
Creating a secondary index on 'sbtest3'...
Creating a secondary index on 'sbtest8'...
Creating a secondary index on 'sbtest10'...
Creating a secondary index on 'sbtest6'...
Creating a secondary index on 'sbtest1'...

運行測試:
1、併發100個thread,events爲1w,間隔報告時間爲10s,測試時間爲10分鐘
[root@slave sysbench]# sysbench oltp_read_only.lua --db-driver=mysql --mysql-user=root --mysql-password='' --mysql-socket=/home/data/mysql3306/mysql.sock --mysql-db=edusoho_e --tables=10 --table-size=50000 --threads=100 --events=10000 --report-interval=10 --time=600 run

2、和上面的大體相同,但不限制請求數量,測試時間爲1分鐘
[root@slave sysbench]# sysbench oltp_read_only.lua --db-driver=mysql --mysql-user=root --mysql-password='' --mysql-socket=/home/data/mysql3306/mysql.sock --mysql-db=edusoho_e --tables=10 --table-size=50000 --threads=100 --report-interval=10 --time=60 run  

[ 10s ] thds: 25 tps: 515.20 qps: 8280.37 (r/w/o: 7247.47/0.00/1032.90) lat (ms,95%): 69.29 err/s: 0.00 reconn/s: 0.00
[ 20s ] thds: 25 tps: 526.22 qps: 8419.66 (r/w/o: 7367.21/0.00/1052.44) lat (ms,95%): 65.65 err/s: 0.00 reconn/s: 0.00
[ 30s ] thds: 25 tps: 522.29 qps: 8354.94 (r/w/o: 7310.36/0.00/1044.58) lat (ms,95%): 66.84 err/s: 0.00 reconn/s: 0.00
[ 40s ] thds: 25 tps: 527.80 qps: 8446.26 (r/w/o: 7390.66/0.00/1055.59) lat (ms,95%): 63.32 err/s: 0.00 reconn/s: 0.00
[ 50s ] thds: 25 tps: 527.52 qps: 8439.37 (r/w/o: 7384.34/0.00/1055.03) lat (ms,95%): 65.65 err/s: 0.00 reconn/s: 0.00
[ 60s ] thds: 25 tps: 525.47 qps: 8407.17 (r/w/o: 7356.33/0.00/1050.83) lat (ms,95%): 64.47 err/s: 0.00 reconn/s: 0.00
SQL statistics:
    queries performed:
        read:                            440580     總select語句
        write:                           0              總insert、delete、update語句
        other:                           62940      commit、unlock table、mutex等
        total:                           503520
    transactions:                        31470  (524.30 per sec.)       TPS
    queries:                             503520 (8388.78 per sec.)      QPS
    ignored errors:                      0      (0.00 per sec.)            忽略的錯誤數
    reconnects:                          0      (0.00 per sec.)

General statistics:
    total time:                          60.0216s           實際壓測時間
    total number of events:              31470         總的事件數,一般和transactions相同

Latency (ms):
         min:                                    1.77       最小響應時間
         avg:                                   47.66      平均響應時間
         max:                                  163.41     最大響應時間
         95th percentile:                       65.65   95%的語句的平均響應時間
         sum:                              1499944.29   總響應時間

Threads fairness:
    events (avg/stddev):           1258.8000/3.88
    execution time (avg/stddev):   59.9978/0.01

清除測試數據:(當然了,可以在數據庫中刪除)
[root@slave sysbench]# sysbench oltp_read_only.lua --db-driver=mysql --mysql-user=root --mysql-password='' --mysql-socket=/home/data/mysql3306/mysql.sock --mysql-db=edusoho_e --tables=10 cleanup

負載監控:
在運行sysbench測試時,壓力一定要慢慢增加(即,慢慢增加  --threads=N ,--events=N 的值),以此來確定負載瓶頸爲多少,絕不能成倍數(100、200、400、800) 的增加壓力。

一方面,壓力瓶頸不易確定,比如:在400的時候,系統load還在承受範圍之內,一旦變爲800的時候,系統load突然急劇變爲原來的十數倍,甚至幾十倍,這個時候,你很難確定瓶頸到底是在400-800之間的哪裏,因爲系統load在達到瓶頸之間,壓力是一直緩慢增長的,一旦突破了某個瓶頸,將會成指數增加

另一方面,成倍數增加測試壓力,一旦突破系統load負載,突然間猛增的壓力,可能會將系統crash。


所以,在使用sysbench測試數據庫瓶頸的時候,一方面需要緩慢增加測試壓力,另一方面,需要同時監控系統load,當超出你設定的系統load時,馬上終止運行。這樣慢慢的,在保證系統load在正常範圍的前提下,測試出最大的數據庫瓶頸。

題外:
sysbench還可以測試磁盤I/O、CPU、memory等,具體的測試用法,請自行百度吧。當然了,對於本文的不當之處,還請各位讀者在下方評論區留言指正,不勝感激!

    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章