當咱們對數據庫進行優化後,只有進行測量系統性能才能知道優化是否有效,這種測量的方式就是基準測試。基準測試的定義以下:html
基準測試是一種測量和評估軟件性能指標的活動用於創建某個時刻的性能基準,以便當系統發生軟/硬件變化時,從新進行基準測試以評估變化對性能的影響前端
咱們能夠這樣認爲:mysql
基準測試是針對系統設置的一種壓力測試,能夠用來觀察系統在不一樣壓力下的行爲。評估系統的容量,觀察系統如何處理不一樣的數據。git
可是基於測試不等同於壓力測試:github
對MySQL進行基準測試的目的:web
一般來講,基準測試有兩種方式:sql
MySQL基準測試的常見指標:數據庫
基準測試中容易忽略的問題:緩存
基準測試的步驟:bash
基準測試數據的收集腳本:
#!/bin/bash # 腳本的運行間隔 INTERVAL=5 # 建立數據文件的存儲目錄 STORE_DIR=/home/mysql/benchmarks mkdir -p $STORE_DIR # 將收集的數據存儲到哪一個目錄下,以及文件前綴 PREFIX=$STORE_DIR/$INTERVAL-sec-status # 設置腳本的運行標識 RUNFILE=$STORE_DIR/running touch $RUNFILE && echo "1" > $RUNFILE # mysql的用戶名和密碼 USER=root PWD=123456 # mysql命令所在的路徑 MYSQL="/usr/local/mysql/bin/mysql -u$USER -p$PWD" # 記錄當前mysql的全局變量 $MYSQL -e "show global variables" >> mysql-variables # 運行標識文件存在就會一直循環 while test -e $RUNFILE; do # 定義腳本運行時的當前時間 file=$(date +%F_%I) # 實現間隔運行該循環 sleep=$(date +%s.%N | awk '{print 5 - ($1 % 5)}') sleep $sleep ts="$(date +"TS %s.%N %F %T")" # 獲取系統負載信息 loadavg="$(uptime)" # 記錄系統負載信息 echo "$ts $loadavg" >> $PREFIX-${file}-status # 記錄當前mysql的全局變量信息 $MYSQL -e "show global status" >> $PREFIX-${file}-status & echo "$ts $loadavg" >> $PREFIX-${file}-innodbstatus # 記錄當前 innodb 的狀態信息 $MYSQL -e "show engine innodb status" >> $PREFIX-${file}-innodbstatus & echo "$ts $loadavg" >> $PREFIX-${file}-processlist # 記錄當前mysql所有鏈接信息列表 $MYSQL -e "show full processlist\G" >> $PREFIX-${file}-processlist & echo $ts done echo Exiting because $RUNFILE does not exists
測試數據分析腳本:
#!/bin/bash awk ' BEGIN { printf "#ts date time load QPS"; fmt=" %.2f"; } /^TS/ { ts = substr($2,1,index($2,".")-1); load = NF -2; diff = ts - prev_ts; printf "\n%s %s %s %s",ts,$3,$4,substr($load,1,length($load)-1); prev_ts=ts; } /Queries/{ printf fmt,($2-Queries)/diff; Queries=$2 } ' "$@" ### 使用示例 ### # sh ./analyze.sh ${測試數據文件路徑} # 如:sh ./analyze.sh /home/mysql/benchmarks/5-sec-status-2020-01-11_04-status
通常來講,咱們都不會本身去編寫基準測試的腳本,由於都有現成的工具。例如,mysql 5.1以上版本都自帶了mysqlslap這個基準測試工具。因爲是自帶的也無需進行單獨的安裝,該工具位於mysql的bin
目錄下。
功能簡介:
經常使用參數說明:
參數 | 說明 |
---|---|
--concurrency |
併發數量,即模擬的客戶端數量,能夠指定多個,使用逗號分隔 |
--iterations |
指定測試的運行次數 |
--auto-generate-sql |
使用系統自動生成的SQL腳原本進行測試 |
--auto-generate-sql-add-autoincrement |
在自動生成的表中增長自增ID |
--auto-generate-sql-load-type |
指定測試中使用的查詢類型(取值:read, write, update, mixed),默認mixed |
--auto-generate-sql-write-number |
指定初始化數據時所生成的數據量 |
--engine |
要測試表的存儲引擎,容許指定多個,使用逗號分隔 |
--no-drop |
指定不清理測試數據 |
--number-of-queries |
指定每個鏈接執行的查詢次數 |
--debug-info |
指定輸出額外的內存及CPU統計信息 |
--number-char-cols |
指定測試表中包含的int 類型的數量 |
--number-int-cols |
指定測試表中包含的varchar 類型的數量 |
--create-schema |
指定用於執行測試的數據庫的名稱 |
--query |
用於指定自定義的SQL腳本 |
--only-print |
指定該參數時,不會運行測試腳本,而是把生成的腳本打印出來 |
使用示例:
[root@localhost ~]# mysqlslap -uroot -p123456 --concurrency=1,50,100,200 --iterations=3 --number-int-cols=5 --number-char-cols=5 --auto-generate-sql --auto-generate-sql-add-autoincrement --engine=myisam,innodb --number-of-queries=10 --create-schema=test
運行該測試後,截取的部分輸出片斷以下:
Benchmark # 運行的是myisam引擎的測試 Running for engine myisam # 運行全部查詢的平均秒數 Average number of seconds to run all queries: 0.020 seconds # 運行全部查詢的最小秒數 Minimum number of seconds to run all queries: 0.018 seconds # 運行全部查詢的最大秒數 Maximum number of seconds to run all queries: 0.022 seconds # 運行查詢的客戶端數 Number of clients running queries: 1 # 每一個客戶端的平均查詢數 Average number of queries per client: 10 Benchmark Running for engine innodb Average number of seconds to run all queries: 0.049 seconds Minimum number of seconds to run all queries: 0.042 seconds Maximum number of seconds to run all queries: 0.059 seconds Number of clients running queries: 1 Average number of queries per client: 10
除了 mysqlslap 這個mysql自帶的基準測試工具以外,還有一個經常使用的工具就是 sysbench。sysbench的功能比mysqlslap更多一些,能測試的點也更全面一些。sysbench除了能夠測試MySQL外,還能測試系統的CPU、IO、內存等方面。
sysbench的GitHub倉庫地址及源碼安裝文檔以下:
通常系統中不會自帶sysbench工具,須要咱們自行安裝,我這裏採用源碼編譯安裝的方式進行安裝。首先到以下地址複製源碼包的下載連接:
而後到Linux上使用wget
命令進行下載:
[root@txy-server ~]# cd /usr/local/src [root@txy-server /usr/local/src]# wget https://github.com/akopytov/sysbench/archive/1.0.19.tar.gz
安裝編譯sysbench時所依賴的一些庫:
[root@txy-server /usr/local/src]# yum -y install make automake libtool pkgconfig libaio-devel mariadb-devel openssl-devel
接着將下載好的源碼包進行解壓縮,並進入到解壓後的目錄:
[root@txy-server /usr/local/src]# tar -zxvf 1.0.19.tar.gz [root@txy-server /usr/local/src]# cd sysbench-1.0.19/
最後參考如下步驟完成編譯安裝:
[root@txy-server /usr/local/src/sysbench-1.0.19]# ./autogen.sh [root@txy-server /usr/local/src/sysbench-1.0.19]# ./configure --with-mysql-includes=/usr/local/mysql/include --with-mysql-libs=/usr/local/mysql/lib [root@txy-server /usr/local/src/sysbench-1.0.19]# make && make install
等待完成編譯安裝後,測試是否安裝成功。我這裏報了個找不到庫文件的錯誤:
[root@txy-server /usr/local/src/sysbench-1.0.19]# sysbench --version sysbench: error while loading shared libraries: libmysqlclient.so.21: cannot open shared object file: No such file or directory
解決方式是創建一個該文件的軟鏈接到/usr/lib64/
目錄下:
[root@txy-server /usr/local/src/sysbench-1.0.19]# ln -s /usr/local/mysql/lib/libmysqlclient.so.21 /usr/lib64/
再次測試,執行成功:
[root@txy-server /usr/local/src/sysbench-1.0.19]# sysbench --version sysbench 1.0.19
sysbench的命令格式以下:
sysbench [options]... [testname] [command]
一、options,是指定測試參數,如下是使用sysbench測試MySQL時經常使用的參數:
--mysql-db
:用於指定基準測試的數據庫名稱,該數據庫必須是已存在的--mysql_storage_engine
:指定測試的MySQL存儲引擎--tables
:執行測試的表的數量--table_size
:指定每一個表中的數據量--threads
:指定測試的併發線程數量--max-time
:指定最大測試時間,單位爲秒--report-interval
:指定間隔多長時間就輸出一次統計信息,單位爲秒--mysql-socket
:指定mysql的.sock
文件路徑,用於鏈接mysql--mysql-user
:指定用於測試時鏈接mysql的用戶--mysql-password
:指定mysql用戶的密碼二、testname,是指定內置的測試類型或測試腳本。內置的測試類型有以下取值:
fileio
:測試文件系統I/O性能cpu
:測試cpu性能memory
:測試內存性能threads
:測試線程性能mutex
:測試互斥鎖性能sysbench [testname] help
,能夠查看各個測試類型所支持的參數除內置測試類型之外的測試,就須要指定測試腳本。sysbench的測試腳本須要使用lua語言編寫,能夠根據實際需求編寫自已的測試腳本,也可使用sysbench自帶的測試腳本。sysbench自帶的lua腳本以下:
[root@txy-server ~]# ls /usr/local/share/sysbench bulk_insert.lua # 用於測試大量的insert操做性能 oltp_common.lua # 公共文件,給其餘腳本引用的,不可直接使用 oltp_delete.lua # 用於測試oltp下的delete操做性能 oltp_insert.lua # 用於測試oltp下的insert操做性能 oltp_point_select.lua # 用於測試oltp下的定點查詢性能,例如根據主鍵查詢 oltp_read_only.lua # 用於測試oltp下的只讀性能 oltp_read_write.lua # 用於測試oltp下的讀寫性能 oltp_update_index.lua # 用於測試更新索引字段的性能 oltp_update_non_index.lua # 用於測試更新無索引字段操做的性能 oltp_write_only.lua # 用於測試oltp下的寫操做性能 select_random_points.lua # 用於測試隨機定點查詢的性能 select_random_ranges.lua # 用於測試隨機範圍讀取的性能 ...
三、command,則是指定一些測試操做,例如運行測試、清除數據或準備數據等:
prepare
:用於測試開始前準備測試數據run
:用於測試數據準備完成後,執行測試cleanup
:用於測試執行完成後清理測試數據如下命令可讓cpu找出10000之內的素數,並統計計算所需耗時,以此得知cpu的性能。須要注意的是,這種方式測試的是單核心性能,而非多核性能:
[root@txy-server ~]# sysbench --cpu-max-prime=10000 cpu run
測試結果以下:
# CPU速度 CPU speed: # 每秒事件數 events per second: 1039.79 General statistics: # 計算出全部素數的總耗時 total time: 10.0005s # 總的事件數 total number of events: 10400 Latency (ms): # 計算出一個素數的最低耗時 min: 0.94 # 平均計算出一個素數的耗時 avg: 0.96 # 計算出一個素數的最長耗時 max: 9.43 # 95%狀況是1.01毫秒計算出一個素數 95th percentile: 1.01 # 合計耗時 sum: 9994.05 # 線程公平性 Threads fairness: events (avg/stddev): 10400.0000/0.00 execution time (avg/stddev): 9.9941/0.00
測試I/O性能須要先準備測試數據,測試數據的大小須要大於物理內存。命令以下:
# 該命令會生成127個測試文件,這些文件合計4G大小 [root@txy-server ~]# sysbench --file-total-size=4G fileio prepare ... Creating file test_file.125 Creating file test_file.126 Creating file test_file.127 4294967296 bytes written in 39.00 seconds (105.04 MiB/sec). [root@txy-server ~]#
數據準備好後,執行測試:
[root@txy-server ~]# sysbench --threads=8 --file-total-size=4G --file-test-mode=rndrw --report-interval=1 fileio run
參數說明:
--threads=8
:設置併發線程數爲8--file-test-mode=rndrw
:指定文件測試模式爲隨機讀寫,即測試磁盤I/O的隨機讀寫性能--report-interval=1
:指定每秒輸出一次統計信息測試結果以下:
File operations: reads/s: 2089.75 writes/s: 1392.67 fsyncs/s: 4553.64 Throughput: # 每秒讀取 read, MiB/s: 32.65 # written, MiB/s: 21.76 General statistics: total time: 10.0778s total number of events: 79973 Latency (ms): min: 0.00 avg: 1.00 max: 58.42 95th percentile: 3.13 sum: 79895.62 Threads fairness: events (avg/stddev): 9996.6250/43.23 execution time (avg/stddev): 9.9870/0.01
最後執行cleanup
操做,清除測試數據:
[root@txy-server ~]# sysbench --file-total-size=4G fileio cleanup
因爲sysbench內置的測試類型沒有MySQL,因此在使用sysbench測試MySQL時,testname須要指定爲測試腳本的路徑。sysbench自帶了一些MySQL的測試腳本,因此無特殊需求的狀況下,咱們也無需本身去編寫測試腳本。接下來,進行一個簡單的演示,看看如何使用測試腳原本測試MySQL的性能。
首先也是須要準備數據,命令以下:
[root@txy-server ~]# sysbench --mysql_storage_engine=innodb --table_size=10000 --mysql-db=test --tables=10 --mysql-socket=/tmp/mysql.sock --mysql-user=root --mysql-password=123456 /usr/local/share/sysbench/oltp_read_write.lua prepare
執行測試:
[root@txy-server ~]# sysbench --mysql_storage_engine=innodb --table_size=10000 --mysql-db=test --tables=10 --mysql-socket=/tmp/mysql.sock --mysql-user=root --mysql-password=123456 /usr/local/share/sysbench/oltp_read_write.lua run
測試結果以下:
SQL statistics: queries performed: # 讀取操做的總數 read: 10444 # 寫操做的總數 write: 2984 # 其餘操做的總數,例如commit等 other: 1492 # 總共執行的操做數量 total: 14920 # 每秒執行的事務數,即TPS,這裏爲每秒74.48次 transactions: 746 (74.48 per sec.) # 每秒查詢的數量,即QPS,這裏爲每秒1489.53次 queries: 14920 (1489.53 per sec.) # 忽略的錯誤次數 ignored errors: 0 (0.00 per sec.) # 重連次數 reconnects: 0 (0.00 per sec.) General statistics: total time: 10.0150s total number of events: 746 Latency (ms): min: 8.86 avg: 13.42 max: 99.97 95th percentile: 20.00 sum: 10009.79 Threads fairness: events (avg/stddev): 746.0000/0.00 execution time (avg/stddev): 10.0098/0.00
一樣,最後須要清理測試數據:
[root@txy-server ~]# sysbench --mysql_storage_engine=innodb --table_size=10000 --mysql-db=test --tables=10 --mysql-socket=/tmp/mysql.sock --mysql-user=root --mysql-password=123456 /usr/local/share/sysbench/oltp_read_write.lua cleanup
若是想要知道測試腳本具體支持哪些參數,其查看方式和內置測試類型是同樣的,只不過把測試類型的名稱換成了腳本而已:
[root@txy-server ~]# sysbench /usr/local/share/sysbench/oltp_read_write.lua help