1. 程式人生 > >MySQL參數優化測試建議

MySQL參數優化測試建議

自己 orm 重連 local 內存大小 足夠 下一個 sql_mod 引擎

一、參數優化前壓力測試
0、優化測試前提
虛擬機vm12.5,OS centos 6.9(系統已優化),cpu2(I5 4288u 2.6GHZ),MEM4GB ,HardDisk:Apple SSD(SM-0512F)

1、模擬數據庫數據
為了測試我們創建一個test1的庫創建一個tb1的表,然後導入20萬行數據,腳本如下:
vim slap.sh

#!/bin/bash  
HOSTNAME="localhost" 
PORT="3306" 
USERNAME="root" 
PASSWORD="123" 
DBNAME="oldboy" 
TABLENAME="lufei" 
#create database 
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e "drop database if exists ${DBNAME}" 
create_db_sql="create database if not exists ${DBNAME}" 
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e "${create_db_sql}" 
#create table 
create_table_sql="create table if not exists ${TABLENAME}(stuid int not null primary key,stuname varchar(20) not null,stusex char(1)   
not null,cardid varchar(20) not null,birthday datetime,entertime datetime,address varchar(100) default null)" 
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} ${DBNAME} -e "${create_table_sql}" 
#insert data to table 
i="1" 
while [ $i -le 200000 ]  
do  
insert_sql="insert into ${TABLENAME}  values($i,‘‘guojialei_$i,‘1‘,‘110011198809163418‘,‘1988-09-16‘,‘2017-09-13‘,‘oldboyedu_$i‘)" 
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} ${DBNAME} -e "${insert_sql}" 
let i++  
done  
#select data  
select_sql="select count(*) from ${TABLENAME}" 
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} ${DBNAME} -e "${select_sql}"

執行腳本:
sh slap.sh

2、檢查數據可用性

mysql -uroot -p123
select count(*) from test1.tb1;

3、在沒有優化之前我們使用mysqlslap來進行壓力測試

mysqlslap --defaults-file=/etc/my.cnf  --concurrency=100 --iterations=1 --create-schema=‘test1‘ --query=‘select * from test1.tb1‘ engine=innodb --number-of-queries=2000 -uroot -p123 -verbose

Benchmark
    Running for engine rbose
    Average number of seconds to run all queries: 31.463 seconds
    Minimum number of seconds to run all queries: 31.463 seconds
    Maximum number of seconds to run all queries: 31.463 seconds
    Number of clients running queries: 100
    Average number of queries per client: 20

--------------------------------mysqlslap使用說明----------------------------
mysqlslap工具介紹
? mysqlslap來自於mariadb包,測試的過程默認生成一個mysqlslap的schema,生成測試表t1,查詢和插入測試數據,mysqlslap庫自動生成,如果已經存在則先刪除。用--only-print來打印實際的測試過程,整個測試完成後不會在數據庫中留下痕跡。

常用選項:

--auto-generate-sql, -a 自動生成測試表和數據,表示用mysqlslap工具自己生成的SQL腳本來測試並發壓力
--auto-generate-sql-load-type=type 測試語句的類型。代表要測試的環境是讀操作還是寫操作還是兩者混合的。取值包括:read,key,write,update和mixed(默認)
--auto-generate-sql-add-auto-increment 代表對生成的表自動添加auto_increment列,從5.1.18版本開始支持
--number-char-cols=N, -x N 自動生成的測試表中包含多少個字符類型的列,默認1
--number-int-cols=N, -y N 自動生成的測試表中包含多少個數字類型的列,默認1
--number-of-queries=N 總的測試查詢次數(並發客戶數×每客戶查詢次數)
--query=name,-q 使用自定義腳本執行測試,例如可以調用自定義的存儲過程或者sql語句來執行測試
--create-schema 代表自定義的測試庫名稱,測試的schema,MySQL中schema也就是database
--commint=N 多少條DML後提交一次
--compress, -C 如服務器和客戶端都支持壓縮,則壓縮信息
--concurrency=N, -c N 表示並發量,即模擬多少個客戶端同時執行select;可指定多個值,以逗號或者--delimiter參數指定值做為分隔符
--engine=engine_name, -e engine_name 代表要測試的引擎,可以有多個,用分隔符隔開
--iterations=N, -i N 測試執行的叠代次數,代表要在不同並發環境下,各自運行測試多少次
--only-print 只打印測試語句而不實際執行
--detach=N 執行N條語句後斷開重連
--debug-info, -T 打印內存和CPU的相關信息

測試示例:

1)單線程測試

[root@centos7 ~]# mysqlslap -a -uroot -p
Enter password: 
Benchmark
        Average number of seconds to run all queries: 0.004 seconds
        Minimum number of seconds to run all queries: 0.004 seconds
        Maximum number of seconds to run all queries: 0.004 seconds
        Number of clients running queries: 1
        Average number of queries per client: 0

2)多線程測試,使用--concurrency來模擬並發連接

[root@centos7 ~]# mysqlslap -uroot -p -a -c 500
Enter password: 
Benchmark
        Average number of seconds to run all queries: 3.384 seconds
        Minimum number of seconds to run all queries: 3.384 seconds
        Maximum number of seconds to run all queries: 3.384 seconds
        Number of clients running queries: 500
        Average number of queries per client: 0

3)同時測試不同的存儲引擎的性能進行對比

[root@centos7 ~]# mysqlslap -uroot -p -a --concurrency=500 --number-of-queries 1000 --iterations=5 --engine=myisam,innodb --debug-info
Enter password: 
Benchmark
        Running for engine myisam
        Average number of seconds to run all queries: 0.192 seconds
        Minimum number of seconds to run all queries: 0.187 seconds
        Maximum number of seconds to run all queries: 0.202 seconds
        Number of clients running queries: 500
        Average number of queries per client: 2

Benchmark
        Running for engine innodb
        Average number of seconds to run all queries: 0.355 seconds
        Minimum number of seconds to run all queries: 0.350 seconds
        Maximum number of seconds to run all queries: 0.364 seconds
        Number of clients running queries: 500
        Average number of queries per client: 2

User time 0.33, System time 0.58
Maximum resident set size 22892, Integral resident set size 0
Non-physical pagefaults 46012, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 31896, Involuntary context switches 0

4)執行一次測試,分別500和1000個並發,執行5000次總查詢

[root@centos7 ~]# mysqlslap -uroot -p -a --concurrency=500,1000 --number-of-queries 5000 --debug-info
Enter password: 
Benchmark
        Average number of seconds to run all queries: 3.378 seconds
        Minimum number of seconds to run all queries: 3.378 seconds
        Maximum number of seconds to run all queries: 3.378 seconds
        Number of clients running queries: 500
        Average number of queries per client: 10

Benchmark
        Average number of seconds to run all queries: 3.101 seconds
        Minimum number of seconds to run all queries: 3.101 seconds
        Maximum number of seconds to run all queries: 3.101 seconds
        Number of clients running queries: 1000
        Average number of queries per client: 5

User time 0.84, System time 0.64
Maximum resident set size 83068, Integral resident set size 0
Non-physical pagefaults 139977, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 31524, Involuntary context switches 3

5)叠代測試

[root@centos7 ~]# mysqlslap -uroot -p -a --concurrency=500 --number-of-queries 5000 --iterations=5 --debug-info
Enter password: 
Benchmark
        Average number of seconds to run all queries: 3.307 seconds
        Minimum number of seconds to run all queries: 3.184 seconds
        Maximum number of seconds to run all queries: 3.421 seconds
        Number of clients running queries: 500
        Average number of queries per client: 10

User time 2.18, System time 1.58
Maximum resident set size 74872, Integral resident set size 0
Non-physical pagefaults 327732, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 73904, Involuntary context switches 3    

二、優化細節

1、參數優化
1.1 Max_connections
(1)簡介
Mysql的最大連接數,如果服務器的並發請求量比較大,可以調高這個值,當然這是要建立在機器能夠支撐的情況下,因為如果連接數越來越多,mysql會為每個連接提供緩沖區,就會開銷的越多的內存,所以需要適當的調整該值,不能隨便去提高設值。
(2)判斷依據

show variables like ‘max_connections‘;
    +-----------------+-------+
    | Variable_name   | Value |
    +-----------------+-------+
    | max_connections | 151   |
    +-----------------+-------+
show status like ‘Max_used_connections‘;
    +----------------------+-------+
    | Variable_name        | Value |
    +----------------------+-------+
    | Max_used_connections | 101   |
    +----------------------+-------+

如果max_used_connections跟max_connections相同,那麽就是max_connections設置過低或者超過服務器的負載上限了,低於10%則設置過大.
(3)修改方式舉例

vim /etc/my.cnf 
Max_connections=1024

1.2 back_log
(1)簡介
mysql能暫存的連接數量,當主要mysql線程在一個很短時間內得到非常多的連接請求時候它就會起作用,如果mysql的連接數據達到max_connections時候,新來的請求將會被存在堆棧中,等待某一連接釋放資源,該推棧的數量及back_log,如果等待連接的數量超過back_log,將不被授予連接資源。

back_log值指出在mysql暫時停止回答新請求之前的短時間內有多少個請求可以被存在推棧中,只有如果期望在一個短時間內有很多連接的時候需要增加它。

(2)判斷依據
show full processlist
發現大量的待連接進程時,就需要加大back_log或者加大max_connections的值

(3)修改方式舉例

vim /etc/my.cnf 
back_log=1024

1.3 wait_timeout和interactive_timeout

(1)簡介

wait_timeout:指的是mysql在關閉一個非交互的連接之前所要等待的秒數
interactive_timeout:指的是mysql在關閉一個交互的連接之前所需要等待的秒數,比如我們在終端上進行mysql管理,使用的即使交互的連接,這時候,如果沒有操作的時間超過了interactive_time設置的時間就會自動的斷開,默認的是28800,可調優為7200。
wait_timeout:如果設置太小,那麽連接關閉的就很快,從而使一些持久的連接不起作用

(2)設置建議
如果設置太大,容易造成連接打開時間過長,在show processlist時候,能看到很多的連接 ,一般希望wait_timeout盡可能低

(3)修改方式舉例

wait_timeout=1200
interactive_timeout=1200

1.4 key_buffer_size
(1)簡介
key_buffer_size指定索引緩沖區的大小,它決定索引處理的速度,尤其是索引讀的速度

(2)設置依據
通過key_read_requests和key_reads可以直到key_baffer_size設置是否合理。

mysql> show variables like "key_buffer_size%";
+-----------------+---------+
| Variable_name   | Value   |
+-----------------+---------+
| key_buffer_size | 8388608 |
+-----------------+---------+
1 row in set (0.00 sec)

mysql> 

mysql> show status like "key_read%";
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Key_read_requests | 10    |
| Key_reads         | 2     |
+-------------------+-------+
2 rows in set (0.00 sec)

mysql> 

一共有10個索引讀取請求,有2個請求在內存中沒有找到直接從硬盤中讀取索引


註:key_buffer_size只對myisam表起作用,即使不使用myisam表,但是內部的臨時磁盤表是myisam表,也要使用該值。
可以使用檢查狀態值created_tmp_disk_tables得知:

mysql> show status like "created_tmp%";
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| Created_tmp_disk_tables | 0     |
| Created_tmp_files       | 6     |
| Created_tmp_tables      | 1     |
+-------------------------+-------+
3 rows in set (0.00 sec)

通常地,我們習慣以 Created_tmp_tables/(Created_tmp_disk_tables + Created_tmp_tables) 或者已各自的一個時段內的差額計算,來判斷基於內存的臨時表利用率。所以,我們會比較關註 Created_tmp_disk_tables 是否過多,從而認定當前服務器運行狀況的優劣。
看以下例子:
在調用mysqldump備份數據時,大概執行步驟如下:

180322 17:39:33       7 Connect     root@localhost on
7 Query       /*!40100 SET @@SQL_MODE=‘‘ */
7 Init DB     guo
7 Query       SHOW TABLES LIKE ‘guo‘
7 Query       LOCK TABLES `guo` READ /*!32311 LOCAL */
7 Query       SET OPTION SQL_QUOTE_SHOW_CREATE=1
7 Query       show create table `guo`
7 Query       show fields from `guo`
7 Query       show table status like ‘guo‘
7 Query       SELECT /*!40001 SQL_NO_CACHE */ * FROM `guo`
7 Query       UNLOCK TABLES
7 Quit

其中,有一步是:show fields from guo。從slow query記錄的執行計劃中,可以知道它也產生了 Tmp_table_on_disk。

所以說,以上公式並不能真正反映到mysql裏臨時表的利用率,有些情況下產生的 Tmp_table_on_disk 我們完全不用擔心,因此沒必要過分關註 Created_tmp_disk_tables,但如果它的值大的離譜的話,那就好好查一下,你的服務器到底都在執行什麽查詢了。

(3)配置方法
key_buffer_size=64M

1.5 query_cache_size
(1)簡介:
查詢緩存簡稱QC,使用查詢緩沖,mysql將查詢結果存放在緩沖區中,今後對於同樣的select語句(區分大小寫),將直接從緩沖區中讀取結果。
一個sql查詢如果以select開頭,那麽mysql服務器將嘗試對其使用查詢緩存。
註:兩個sql語句,只要想差哪怕是一個字符(列如大小寫不一樣;多一個空格等),那麽這兩個sql將使用不同的一個cache。
(2)判斷依據

mysql> show status like "%Qcache%";
+-------------------------+---------+
| Variable_name           | Value   |
+-------------------------+---------+
| Qcache_free_blocks      | 1       |
| Qcache_free_memory      | 1031360 |
| Qcache_hits             | 0       |
| Qcache_inserts          | 0       |
| Qcache_lowmem_prunes    | 0       |
| Qcache_not_cached       | 2002    |
| Qcache_queries_in_cache | 0       |
| Qcache_total_blocks     | 1       |
+-------------------------+---------+
8 rows in set (0.00 sec)

---------------------狀態說明--------------------

Qcache_free_blocks:緩存中相鄰內存塊的個數。如果該值顯示較大,則說明Query Cache 中的內存碎片較多了,FLUSH QUERY CACHE會對緩存中的碎片進行整理,從而得到一個空閑塊。
註:當一個表被更新之後,和它相關的cache blocks將被free。但是這個block依然可能存在隊列中,除非是在隊列的尾部。可以用FLUSH QUERY CACHE語句來清空free blocks

Qcache_free_memory:Query Cache 中目前剩余的內存大小。通過這個參數我們可以較為準確的觀察出當前系統中的Query Cache 內存大小是否足夠,是需要增加還是過多了。

Qcache_hits:表示有多少次命中緩存。我們主要可以通過該值來驗證我們的查詢緩存的效果。數字越大,緩存效果越理想。

Qcache_inserts:表示多少次未命中然後插入,意思是新來的SQL請求在緩存中未找到,不得不執行查詢處理,執行查詢處理後把結果insert到查詢緩存中。這樣的情況的次數越多,表示查詢緩存應用到的比較少,效果也就不理想。當然系統剛啟動後,查詢緩存是空的,這很正常。

Qcache_lowmem_prunes:多少條Query 因為內存不足而被清除出Query Cache。通過“Qcache_lowmem_prunes”和“Qcache_free_memory”相互結合,能夠更清楚的了解到我們系統中Query Cache 的內存大小是否真的足夠,是否非常頻繁的出現因為內存不足而有Query 被換出。這個數字最好長時間來看;如果這個數字在不斷增長,就表示可能碎片非常嚴重,或者內存很少。(上面的free_blocks和free_memory可以告訴您屬於哪種情況)

Qcache_not_cached:不適合進行緩存的查詢的數量,通常是由於這些查詢不是 SELECT 語句或者用了now()之類的函數。

Qcache_queries_in_cache:當前Query Cache 中cache 的Query 數量;

Qcache_total_blocks:當前Query Cache 中的block 數量;。

(3)配置示例

mysql> show variables like ‘%query_cache%‘ ;
+------------------------------+---------+
| Variable_name                | Value   |
+------------------------------+---------+
| have_query_cache             | YES     |
| query_cache_limit            | 1048576 |
| query_cache_min_res_unit     | 4096    |
| query_cache_size             | 1048576 |
| query_cache_type             | OFF     |
| query_cache_wlock_invalidate | OFF     |
+------------------------------+---------+
6 rows in set (0.00 sec)

mysql> 

-------------------配置說明-------------------------------
以上信息可以看出query_cache_type為off表示不緩存任何查詢
各字段的解釋:

query_cache_limit:超過此大小的查詢將不緩存
query_cache_min_res_unit:緩存塊的最小大小,query_cache_min_res_unit的配置是一柄”雙刃劍”,默認是4KB,設置值大對大數據查詢有好處,但如果你的查詢都是小數據查詢,就容易造成內存碎片和浪費。
query_cache_size:查詢緩存大小 (註:QC存儲的最小單位是1024byte,所以如果你設定了一個不是1024的倍數的值,這個值會被四舍五入到最接近當前值的等於1024的倍數的值。)
query_cache_type:緩存類型,決定緩存什麽樣的查詢,註意這個值不能隨便設置,必須設置為數字,可選項目以及說明如下:
如果設置為0,那麽可以說,你的緩存根本就沒有用,相當於禁用了。
如果設置為1,將會緩存所有的結果,除非你的select語句使用SQL_NO_CACHE禁用了查詢緩存。
如果設置為2,則只緩存在select語句中通過SQL_CACHE指定需要緩存的查詢。

修改/etc/my.cnf,配置完後的部分文件如下:

query_cache_size=256M
query_cache_type=1

1.6 max_connect_errors
max_connect_errors是一個mysql中與安全有關的計數器值,它負責阻止過多嘗試失敗的客戶端以防止暴力破解密碼等情況,當超過指定次數,mysql服務器將禁止host的連接請求,直到mysql服務器重啟或通過flush hosts命令清空此host的相關信息 max_connect_errors的值與性能並無太大關系。

修改/etc/my.cnf文件,在[mysqld]下面添加如下內容
max_connect_errors=2000

1.7 sort_buffer_size
(1)簡介:
每個需要進行排序的線程分配該大小的一個緩沖區。增加這值加速ORDER BY 或GROUP BY操作,
(2)配置依據
Sort_Buffer_Size並不是越大越好,由於是connection級的參數,過大的設置+高並發可能會耗盡系統內存資源。
列如:500個連接將會消耗500*sort_buffer_size(2M)=1G內存
(3)配置方法
修改/etc/my.cnf文件,在[mysqld]下面添加如下:
sort_buffer_size=1M

1.8 max_allowed_packet
(1)簡介:
mysql根據配置文件會限制,server接受的數據包大小。
(2)配置依據:
有時候大的插入和更新會受max_allowed_packet參數限制,導致寫入或者更新失敗,更大值是1GB,必須設置1024的倍數
(3)配置方法:
max_allowed_packet=32M

1.9 join_buffer_size

用於表間關聯緩存的大小,和sort_buffer_size一樣,該參數對應的分配內存也是每個連接獨享。

1.10 thread_cache_size
(1)簡介
服務器線程緩存,這個值表示可以重新利用保存在緩存中線程的數量,當斷開連接時,那麽客戶端的線程將被放到緩存中以響應下一個客戶而不是銷毀(前提是緩存數未達上限),如果線程重新被請求,那麽請求將從緩存中讀取,如果緩存中是空的或者是新的請求,那麽這個線程將被重新創建,如果有很多新的線程,增加這個值可以改善系統性能.
(2)配置依據
通過比較 Connections 和 Threads_created 狀態的變量,可以看到這個變量的作用。
設置規則如下:1GB 內存配置為8,2GB配置為16,3GB配置為32,4GB或更高內存,可配置更大。
服務器處理此客戶的線程將會緩存起來以響應下一個客戶而不是銷毀(前提是緩存數未達上限)

試圖連接到MySQL(不管是否連接成功)的連接數

mysql>  show status like ‘threads_%‘;
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_cached    | 8     |
| Threads_connected | 2     |
| Threads_created   | 4783  |
| Threads_running   | 1     |
+-------------------+-------+
4 rows in set (0.00 sec)
Threads_cached :代表當前此時此刻線程緩存中有多少空閑線程。
Threads_connected :代表當前已建立連接的數量,因為一個連接就需要一個線程,所以也可以看成當前被使用的線程數。
Threads_created:代表從最近一次服務啟動,已創建線程的數量,如果發現Threads_created值過大的話,表明MySQL服務器一直在創建線程,這也是比較耗資源,可以適當增加配置文件中thread_cache_size值。
Threads_running :代表當前激活的(非睡眠狀態)線程數。並不是代表正在使用的線程數,有時候連接已建立,但是連接處於sleep狀態。

(3)配置方法:
thread_cache_size=32

1.11 innodb_buffer_pool_size
(1)簡介
對於InnoDB表來說,innodb_buffer_pool_size的作用就相當於key_buffer_size對於MyISAM表的作用一樣。
(2)配置依據:
InnoDB使用該參數指定大小的內存來緩沖數據和索引。
對於單獨的MySQL數據庫服務器,最大可以把該值設置成物理內存的80%,一般我們建議不要超過物理內存的70%。

mysql> SHOW GLOBAL STATUS LIKE ‘Innodb_buffer_pool%‘
+---------------------------------------+-------------+
| Variable_name                         | Value       |
+---------------------------------------+-------------+
| Innodb_buffer_pool_dump_status        | not started |
| Innodb_buffer_pool_load_status        | not started |
| Innodb_buffer_pool_pages_data         | 1557        |
| Innodb_buffer_pool_bytes_data         | 25509888    |
| Innodb_buffer_pool_pages_dirty        | 0           |
| Innodb_buffer_pool_bytes_dirty        | 0           |
| Innodb_buffer_pool_pages_flushed      | 2305        |
| Innodb_buffer_pool_pages_free         | 63977       |
| Innodb_buffer_pool_pages_misc         | 2           |
| Innodb_buffer_pool_pages_total        | 65536       |
| Innodb_buffer_pool_read_ahead_rnd     | 0           |
| Innodb_buffer_pool_read_ahead         | 64          |
| Innodb_buffer_pool_read_ahead_evicted | 0           |
| Innodb_buffer_pool_read_requests      | 32036288    |
| Innodb_buffer_pool_reads              | 600         |
| Innodb_buffer_pool_wait_free          | 0           |
| Innodb_buffer_pool_write_requests     | 280891      |
+---------------------------------------+-------------+
17 rows in set (0.00 sec)

mysql>
Innodb_buffer_pool_pages_data
The number of pages in the InnoDB buffer pool containing data. The number includes both dirty and
clean pages.

Innodb_buffer_pool_pages_total
The total size of the InnoDB buffer pool, in pages.

Innodb_page_size
InnoDB page size (default 16KB). Many values are counted in pages; the page size enables them to be
easily converted to bytes

(3)配置方法
innodb_buffer_pool_size=1024M

1.12 innodb_flush_log_at_trx_commit
(1)簡介
主要控制了innodb將log buffer中的數據寫入日誌文件並flush磁盤的時間點,取值分別為0、1、2三個。

0,表示當事務提交時,不做日誌寫入操作,而是每秒鐘將log buffer中的數據寫入日誌文件並flush磁盤一次;
1,則在每秒鐘或是每次事物的提交都會引起日誌文件寫入、flush磁盤的操作,確保了事務的ACID;
2,每次事務提交引起寫入日誌文件的動作,但每秒鐘完成一次flush磁盤操作。

(2)配置依據

實際測試發現,該值對插入數據的速度影響非常大,設置為2時插入10000條記錄只需要2秒,設置為0時只需要1秒,而設置為1時則需要229秒。因此,MySQL手冊也建議盡量將插入操作合並成一個事務,這樣可以大幅提高速度。
根據MySQL官方文檔,在允許丟失最近部分事務的危險的前提下,可以把該值設為0或2。
(3)配置方法
innodb_flush_log_at_trx_commit=1

1.13 innodb_thread_concurrency
(1)簡介
此參數用來設置innodb線程的並發數量,默認值為0表示不限制。
(2)配置依據
在官方doc上,對於innodb_thread_concurrency的使用,也給出了一些建議,如下:

如果一個工作負載中,並發用戶線程的數量小於64,建議設置innodb_thread_concurrency=0;
如果工作負載一直較為嚴重甚至偶爾達到頂峰,建議先設置innodb_thread_concurrency=128,
並通過不斷的降低這個參數,96, 80, 64等等,直到發現能夠提供最佳性能的線程數,
例如,假設系統通常有40到50個用戶,但定期的數量增加至60,70,甚至200。你會發現,
性能在80個並發用戶設置時表現穩定,如果高於這個數,性能反而下降。在這種情況下,
建議設置innodb_thread_concurrency參數為80,以避免影響性能。
如果你不希望InnoDB使用的虛擬CPU數量比用戶線程使用的虛擬CPU更多(比如20個虛擬CPU),
建議通過設置innodb_thread_concurrency 參數為這個值(也可能更低,這取決於性能體現),
如果你的目標是將MySQL與其他應用隔離,你可以考慮綁定mysqld進程到專有的虛擬CPU。
但是需 要註意的是,這種綁定,在myslqd進程一直不是很忙的情況下,可能會導致非最優的硬件使用率。在這種情況下,
你可能會設置mysqld進程綁定的虛擬 CPU,允許其他應用程序使用虛擬CPU的一部分或全部。
在某些情況下,最佳的innodb_thread_concurrency參數設置可以比虛擬CPU的數量小。
定期檢測和分析系統,負載量、用戶數或者工作環境的改變可能都需要對innodb_thread_concurrency參數的設置進行調整。

(3)配置方法:
innodb_thread_concurrency=8

1.14 innodb_log_buffer_size

此參數確定些日誌文件所用的內存大小,以M為單位。緩沖區更大能提高性能,對於較大的事務,可以增大緩存大小。
innodb_log_buffer_size=8M

1.15. innodb_log_file_size = 50M
此參數確定數據日誌文件的大小,以M為單位,更大的設置可以提高性能.

1.16. innodb_log_files_in_group = 3
為提高性能,MySQL可以以循環方式將日誌文件寫到多個文件。推薦設置為3

1.17.read_buffer_size = 1M
MySql讀入緩沖區大小。對表進行順序掃描的請求將分配一個讀入緩沖區,MySql會為它分配一段內存緩沖區。如果對表的順序掃描請求非常頻繁,並且你認為頻繁掃描進行得太慢,可以通過增加該變量值以及內存緩沖區大小提高其性能。和 sort_buffer_size一樣,該參數對應的分配內存也是每個連接獨享

18.read_rnd_buffer_size = 1M
MySql的隨機讀(查詢操作)緩沖區大小。當按任意順序讀取行時(例如,按照排序順序),將分配一個隨機讀緩存區。進行排序查詢時,MySql會首先掃描一遍該緩沖,以避免磁盤搜索,提高查詢速度,如果需要排序大量數據,可適當調高該值。但MySql會為每個客戶連接發放該緩沖空間,所以應盡量適當設置該值,以避免內存開銷過大。
註:順序讀是指根據索引的葉節點數據就能順序地讀取所需要的行數據。隨機讀是指一般需要根據輔助索引葉節點中的主鍵尋找實際行數據,而輔助索引和主鍵所在的數據段不同,因此訪問方式是隨機的。

19.bulk_insert_buffer_size = 8M
批量插入數據緩存大小,可以有效提高插入效率,默認為8M

1.20.binary log

log-bin=/data/mysql-bin
binlog_cache_size = 2M //為每個session 分配的內存,在事務過程中用來存儲二進制日誌的緩存, 提高記錄bin-log的效率。沒有什麽大事務,dml也不是很頻繁的情況下可以設置小一點,如果事務大而且多,dml操作也頻繁,則可以適當的調大一點。前者建議是--1M,後者建議是:即 2--4M
max_binlog_cache_size = 8M //表示的是binlog 能夠使用的最大cache 內存大小
max_binlog_size= 512M //指定binlog日誌文件的大小,如果當前的日誌大小達到max_binlog_size,還會自動創建新的二進制日誌。你不能將該變量設置為大於1GB或小於4096字節。默認值是1GB。在導入大容量的sql文件時,建議關閉sql_log_bin,否則硬盤扛不住,而且建議定期做刪除。

expire_logs_days = 7 //定義了mysql清除過期日誌的時間。
二進制日誌自動刪除的天數。默認值為0,表示“沒有自動刪除”。

innodb_max_dirty_pages_pct
innodb_additional_mem_pool_size (於2G內存的機器,推薦值是20M。32G內存的?100M)
transaction_isolation

1.21 安全參數

Innodb_flush_method=(O_DIRECT, fdatasync)

1、fdatasync

(1)在數據頁需要持久化時,首先將數據寫入OS buffer中,然後由os決定什麽時候寫入磁盤
(2)在redo buffuer需要持久化時,首先將數據寫入OS buffer中,然後由os決定什麽時候寫入磁盤
但,如果innodb_flush_log_at_trx_commit=1的話,日誌還是直接每次commit直接寫入磁盤

2、 Innodb_flush_method=O_DIRECT

(1)在數據頁需要持久化時,直接寫入磁盤
(2)在redo buffuer需要持久化時,首先將數據寫入OS buffer中,然後由os決定什麽時候寫入磁盤
但,如果innodb_flush_log_at_trx_commit=1的話,日誌還是直接每次commit直接寫入磁盤

最高安全模式:
        innodb_flush_log_at_trx_commit=1
        innodb_flush_method=O_DIRECT
最高性能模式:
        innodb_flush_log_at_trx_commit=0
        innodb_flush_method=fdatasync

一般情況下,我們更偏向於安全。

“雙一標準”
        innodb_flush_log_at_trx_commit=1        
        sync_binlog=1                    
        innodb_flush_method=O_DIRECT

三、參數優化結果

[mysqld]
basedir=/application/mysql
datadir=/application/mysql/data
socket=/tmp/mysql.sock
log-error=/var/log/mysql.log
log_bin=/data/binlog/mysql-bin
binlog_format=row
skip-name-resolve
server-id=52
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
relay_log_purge=0
max_connections=1024
back_log=128
wait_timeout=60
interactive_timeout=7200
key_buffer_size=16M
query_cache_size=64M
query_cache_type=1
query_cache_limit=50M
max_connect_errors=20
sort_buffer_size=2M
max_allowed_packet=32M
join_buffer_size=2M
thread_cache_size=200
innodb_buffer_pool_size=1024M
innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=32M
innodb_log_file_size=128M
innodb_log_files_in_group=3
binlog_cache_size=2M
max_binlog_cache_size=8M
max_binlog_size=512M
expire_logs_days=7
read_buffer_size=2M
read_rnd_buffer_size=2M
bulk_insert_buffer_size=8M
[client]
socket=/tmp/mysql.sock  

再次壓力測試 :

[root@db02 ~]# mysqlslap --defaults-file=/etc/my.cnf >  --concurrency=100 --iterations=1 --create-schema=‘test1‘ > --query=‘select * from test1.tb1‘ engine=innodb > --number-of-queries=2000 -uroot -p123 -verbose
Warning: Using a password on the command line interface can be insecure.
Benchmark
    Running for engine rbose
    Average number of seconds to run all queries: 7.271 seconds
    Minimum number of seconds to run all queries: 7.271 seconds
    Maximum number of seconds to run all queries: 7.271 seconds
    Number of clients running queries: 100
    Average number of queries per client: 20

對比之前:

mysqlslap --defaults-file=/etc/my.cnf  --concurrency=100 --iterations=1 --create-schema=‘test1‘ --query=‘select * from test1.tb1‘ engine=innodb --number-of-queries=2000 -uroot -p123 -verbose

Benchmark
    Running for engine rbose
    Average number of seconds to run all queries: 31.463 seconds
    Minimum number of seconds to run all queries: 31.463 seconds
    Maximum number of seconds to run all queries: 31.463 seconds
    Number of clients running queries: 100
    Average number of queries per client: 20

MySQL參數優化測試建議