1. 程式人生 > >用mysqlslap對MySQL進行壓力測試

用mysqlslap對MySQL進行壓力測試

MySQL5.1地的確提供了好多有力的工具來幫助我們DBA進行資料庫管理。
現在看一下這個壓力測試工具mysqlslap.
關於他的選項手冊上以及--help介紹的很詳細。
我解釋一下一些常用的選項。
這裡要注意的幾個選項:
--concurrency代表併發數量,多個可以用逗號隔開,當然你也可以用自己的分隔符隔開,這個時候要用到--delimiter開關。
--engines代表要測試的引擎,可以有多個,用分隔符隔開。
--iterations代表要執行這些測試多少次。
--auto-generate-sql 代表用系統自己生成的SQL指令碼來測試。
--auto-generate-sql-load-type 代表要測試的是讀還是寫還是兩者混合的(read,write,update,mixed)

--number-of-queries 代表總共要執行多少次查詢。每個客戶執行的查詢數量可以用查詢總數/併發數來計算。比如倒數第二個結果2=200/100。
--debug-info 代表要額外輸出CPU以及記憶體的相關資訊。
--number-int-cols 代表示例表中的INTEGER型別的屬性有幾個。
--number-char-cols 意思同上。
--create-schema 代表自己定義的模式(在MySQL中也就是庫)。
--query 代表自己的SQL指令碼。
--only-print 如果只想列印看看SQL語句是什麼,可以用這個選項。

現在來看一些我測試的例子。

1、用自帶的SQL指令碼來測試。
MySQL版本為5.1.23
[root@localhost ~]# mysqlslap --defaults-file=/usr/local/mysql-maria/my.cnf --concurrency=50,100,200 --iterations=--number-int-cols=--number-char-cols=35 --auto-generate-sql --auto-generate-sql-add-autoincrement --auto-generate-sql-load-type=mixed --engine=myisam,innodb --number-of-queries=200 --debug-info
 -uroot -p1 -S/tmp/mysql_3310.sock


Benchmark
        Running for engine myisam
        Average number of seconds to run all queries: 0.063 seconds
        Minimum number of seconds to run all queries: 0.063 seconds
        Maximum number of seconds to run all queries: 0.063 seconds
        Number of clients running queries: 50
        Average number of queries per client: 4

Benchmark
        Running for engine myisam
        Average number of seconds to run all queries: 0.070 seconds
        Minimum number of seconds to run all queries: 0.070 seconds
        Maximum number of seconds to run all queries: 0.070 seconds
        Number of clients running queries: 100
        Average number of queries per client: 2

Benchmark
        Running for engine myisam
        Average number of seconds to run all queries: 0.092 seconds
        Minimum number of seconds to run all queries: 0.092 seconds
        Maximum number of seconds to run all queries: 0.092 seconds
        Number of clients running queries: 200
        Average number of queries per client: 1

Benchmark
        Running for engine innodb
        Average number of seconds to run all queries: 0.115 seconds
        Minimum number of seconds to run all queries: 0.115 seconds
        Maximum number of seconds to run all queries: 0.115 seconds
        Number of clients running queries: 50
        Average number of queries per client: 4

Benchmark
        Running for engine innodb
        Average number of seconds to run all queries: 0.134 seconds
        Minimum number of seconds to run all queries: 0.134 seconds
        Maximum number of seconds to run all queries: 0.134 seconds
        Number of clients running queries: 100
        Average number of queries per client: 2

Benchmark
        Running for engine innodb
        Average number of seconds to run all queries: 0.192 seconds
        Minimum number of seconds to run all queries: 0.192 seconds
        Maximum number of seconds to run all queries: 0.192 seconds
        Number of clients running queries: 200
        Average number of queries per client: 1


User time 0.06, System time 0.15
Maximum resident set size 0, Integral resident set size 0
Non-physical pagefaults 5803, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 8173, Involuntary context switches 528


我來解釋一下結果的含義。
拿每個引擎最後一個Benchmark示例。
對於INNODB引擎,200個客戶端同時執行這些SQL語句平均要花0.192秒。相應的MYISAM為0.092秒。

2、用我們自己定義的SQL 指令碼來測試。
這些資料在另外一個MySQL例項上。版本為5.0.45
先看一下這兩個表的相關資料。
1)、總記錄數。
mysql> select table_rows as rows from information_schema.tables where table_schema='t_girl' and table_name='article';
+--------+
| rows   |
+--------+
| 296693 |
+--------+
1 row in set (0.01 sec)

mysql> select table_rows as rows from information_schema.tables where table_schema='t_girl' and table_name='category';
+------+
| rows |
+------+
| 113  |
+------+
1 row in set (0.00 sec)

2)、總列數。
mysql> select count(*) as column_total from information_schema.columns where table_schema = 't_girl' and table_name = 'article';
+--------------+
| column_total |
+--------------+
| 32           |
+--------------+
1 row in set (0.01 sec)

mysql> select count(*) as column_total from information_schema.columns where table_schema = 't_girl' and table_name = 'category';
+--------------+
| column_total |
+--------------+
| 9            
+--------------+
1 row in set (0.01 sec)


3)、呼叫的儲存過程
DELIMITER $$

DROP PROCEDURE IF EXISTS `t_girl`.`sp_get_article`$$

CREATE DEFINER=`root`@`%` PROCEDURE `sp_get_article`(IN f_category_id int,
 IN f_page_size int, IN f_page_no int
)
BEGIN
  set @stmt = 'select a.* from article as a inner join ';
  set @stmt = concat(@stmt,'(select a.aid from article as a ');
  if f_category_id != 0 then
    set @stmt = concat(@stmt,' inner join (select cid from category where cid = ',f_category_id,' or parent_id = ',f_category_id,') as b on a.category_id = b.cid');
  end if;
  if f_page_size >&& f_page_no > 0 then
    set @stmt = concat(@stmt,' limit ',(f_page_no-1)*f_page_size,',',f_page_size);
  end if; 
 
  set @stmt = concat(@stmt,') as b on (a.aid = b.aid)');
  prepare s1 from @stmt;
  execute s1;
  deallocate prepare s1;
  set @stmt = NULL;
END$$

DELIMITER ;

4)、我們用mysqlslap來測試
以下得這個例子代表用mysqlslap來測試併發數為25,50,100的呼叫儲存過程,並且總共呼叫5000次。
[[email protected] ~]# mysqlslap --defaults-file=/usr/local/mysql-maria/my.cnf --concurrency=25,50,100 --iterations=--query='call t_girl.sp_get_article(2,10,1);' --number-of-queries=5000 --debug-info -uroot --S/tmp/mysql50.sock
Enter password: 
Benchmark
        Average number of seconds to run all queries: 3.507 seconds
        Minimum number of seconds to run all queries: 3.507 seconds
        Maximum number of seconds to run all queries: 3.507 seconds
        Number of clients running queries: 25
        Average number of queries per client: 200
平均每個併發執行200個查詢用了3.507秒。
Benchmark
        Average number of seconds to run all queries: 3.742 seconds
        Minimum number of seconds to run all queries: 3.742 seconds
        Maximum number of seconds to run all queries: 3.742 seconds
        Number of clients running queries: 50
        Average number of queries per client: 100

Benchmark
        Average number of seconds to run all queries: 3.697 seconds
        Minimum number of seconds to run all queries: 3.697 seconds
        Maximum number of seconds to run all queries: 3.697 seconds
        Number of clients running queries: 100
        Average number of queries per client: 50


User time 0.87, System time 0.33
Maximum resident set size 0, Integral resident set size 0
Non-physical pagefaults 1877, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 27218, Involuntary context switches 3100


看一下SHOW PROCESSLIST 結果
mysql> show processlist;
+------+------+--------------------+--------------------+---------+-------+--------------------+------------------------------------------------------------------------------------------------------+
| Id   | User | Host               | db                 | Command | Time  | State              | Info                                                                                                 |
+------+------+--------------------+--------------------+---------+-------+--------------------+------------------------------------------------------------------------------------------------------+
…………
| 3177 | root | %                  | t_girl             | Query   |     0 | NULL               | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3178 | root | %                  | t_girl             | Query   |     0 | NULL               | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3179 | root | %                  | t_girl             | Query   |     0 | NULL               | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3181 | root | %                  | t_girl             | Query   |     0 | NULL               | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3180 | root | %                  | t_girl             | Query   |     0 | NULL               | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3182 | root | %                  | t_girl             | Query   |     0 | NULL               | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3183 | root | %                  | t_girl             | Query   |     0 | NULL               | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3187 | root | %                  | t_girl             | Query   |     0 | removing tmp table | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3186 | root | %                  | t_girl             | Query   |     0 | NULL               | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3194 | root | %                  | t_girl             | Query   |     0 | NULL               | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3203 | root | %                  | t_girl             | Query   |     0 | NULL               | deallocate prepare s1                                                                                | 
…………
| 3221 | root | %                  | t_girl             | Query   |     0 | NULL               | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3222 | root | %                  | t_girl             | Query   |     0 | NULL               | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3223 | root | %                  | t_girl             | Query   |     0 | NULL               | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3224 | root | %                  | t_girl             | Query   |     0 | removing tmp table | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3225 | root | %                  | t_girl             | Query   |     0 | NULL               | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
| 3226 | root | %                  | t_girl             | Query   |     0 | NULL               | select a.* from article as a inner join (select a.aid from article as a  inner join (select cid from | 
+------+------+--------------------+--------------------+---------+-------+--------------------+------------------------------------------------------------------------------------------------------+
55 rows in set (0.00 sec)

上面的測試語句其實也可以這樣寫

[[email protected] ~]# mysqlslap --defaults-file=/usr/local/mysql-maria/my.cnf --concurrency=25,50,100 --iterations=--create-schema='t_girl' --query='call sp_get_article(2,10,1);' --number-of-queries=5000 --debug-info -uroot --S/tmp/mysql50.sock


小總結一下。
mysqlslap對於模擬多個使用者同時對MySQL發起“進攻”提供了方便。同時詳細的提供了“高負荷攻擊MySQL”的詳細資料報告。
而且如果你想對於多個引擎的效能。這個工具再好不過了。