1. 程式人生 > 實用技巧 >mysql-通用優化配置詳解

mysql-通用優化配置詳解

mysql-通用優化配置詳解

此處只是將通用優化配置項進行解釋說明,再具體的優化需要根據自己業務需求進行相應配置

文章轉載自NLOneDay

transaction_isolation = READ-COMMITTED

解讀:事務隔離級別:Oracle、SQL Server等商業資料庫預設級別為READ-COMMITTED,MySQL預設為REPEATABLE-READ,它利用自身獨有的Gap Lock解決了"幻讀",但也因次相比於READ-COMMITTED級別的Record Lock,REPEATABLE-READ的事務併發插入效能受到很大的限制

設定:隔離級別的選擇取決實際的業務需求(安全和效能的權衡)。如果不是金融、電信等事務級別要求很高的業務,建議設定成:transaction_isolation = READ-COMMITTED

innodb_buffer_pool_size = xx[M|G]

解讀:InNoDB緩衝池大小,它決定mysql可以在記憶體中快取多少資料和索引,而不是每次都從磁碟上讀取

設定:如果是專用mysql伺服器,一般設定為作業系統記憶體的75%,但至少保留2G記憶體用於作業系統維護和MySQL異常事務處理

innodb_buffer_pool_instances = xx

解讀:InnoDB緩衝池例項個數,InnoDB緩衝池是通過一整個連結串列的方式來管理頁面(段、簇、頁)的,由於互斥鎖的存在(保護連結串列中的頁面),高併發事務下,頁面的讀取和寫入就需要鎖的競爭和等待。通過設定innodb_buffer_pool_instances,將一整個連結串列劃分為多個,每個緩衝池例項管理自己的頁面和互斥,從而提高效率

設定:如果緩衝池比較大(8G以上),可以按照innodb_buffer_pool_size / innodb_buffer_pool_instances = 1G進行設定,但如果緩衝池特別大(32G以上),可以按照每個例項2~3G進行劃分,例項數不是越多越好,多例項代表多執行緒,執行緒的開銷(CPU、MEM)也得考慮

innodb_log_file_size = xxM

解讀:InnoDB日誌檔案大小(Redo Log),它將事務對InnoDB表的修改記錄儲存在ib_logfile0、ib_logfile1中。innodb_log_file_size越大,緩衝池中的髒資料需要檢查點(checkpoint)進行刷盤的頻率就越少,從而減少磁碟IO來降低高併發負載造成的峰值。但日誌檔案也不是越大約好,由於記憶體中髒資料刷盤的頻率減少,一旦資料庫發生異常崩潰,資料庫重啟時從innodb_log_file中讀取資料進行恢復的時間越長

設定:一般選取業務高峰期一個小時的日誌量作為標準,計算過程如下

]# mysql -uroot -p -e "show engine innodb status\G"|grep "Log sequence number" \
> && sleep 60 \
> && mysql -uroot -p -e "show engine innodb status\G"|grep "Log sequence number"

#輸出
Log sequence number 149949388055
Log sequence number 149959622102

#計算
(149949388055 - 149959622102) / 1024 / 1024 = 10M
10 / 60 * 3600 = 600M

#解釋
Log sequence number代表InnoDB執行至今寫入日誌的總位元組數,兩次列印之間執行緒休眠60秒
得到一分鐘之內事務日誌記錄的總量10M,再轉換成一個小時的總量600M
因為'ib_logfile0、ib_logfile1'兩個檔案迴圈寫入,一個檔案為300M
最終,innodb_log_file_size=300M

innodb_flush_log_at_trx_commit = x

解讀:InnoDB事務日誌刷盤時機

當 x = 0 時,事務提交到日誌緩衝區,後臺Write執行緒每隔一秒將緩衝區的日誌寫入系統緩衝區,實際寫入物理日誌檔案的時機取決於作業系統
當 x = 1 時,事務提交到日誌緩衝區,Master執行緒同步將緩衝區的日誌直接寫入物理日誌檔案,這完全符合InnoDB ACID事務標準,資料不會丟失
當 x = 2 時,事務提交到系統緩衝區,Master執行緒每隔一秒將系統緩衝區的日誌寫入物理日誌檔案

設定:安全性(1>2>0)速度(0>2>1),根據實際業務需求選擇合理的刷盤時機

- innodb_flush_log_at_trx_commit = 0
transaction --> innodb_log_buffer -- 每隔1s --> os_cache -- 作業系統控制 --> innodb_log_file
- innodb_flush_log_at_trx_commit = 1
transaction --> innodb_log_buffer -- 每次 --> innodb_log_file 
- innodb_flush_log_at_trx_commit = 2
transaction --> os_cache -- 每隔1s --> innodb_log_file

innodb_file_per_table = [ON|OFF]

解讀:InnoDB獨立表空間,innodb_file_per_table = ON表示每張表在獨立的物理檔案中(.ibd)儲存資料和索引,innodb_file_per_table = OFF表示所有表都共享表空間即一個物理檔案(ibdata1)。如果通過drop/truncate table操作,獨立表空間的物理儲存會立即被回收(刪除/初始化),而共享表空間不會被回收且只會一直增大

設定:innodb_file_per_table = ON,但需要注意的是,獨立表空間只儲存資料和索引,如回滾日誌緩衝(Undo Log)、插入索引緩衝(Insert Buffer)、二次寫緩衝(Doublewrite Buffer)等還是放在共享表空間

query_cache_size = 0

解讀:查詢快取大小,它是為了在追蹤表的資料未發生變化時,本次查詢命中之前的查詢語句,從而跳過解析、優化、執行階段,直接返回緩衝池中的資料。但實際在OLTP系統中,極少能命中查詢快取(前提是資料庫中的資料變化頻率很小),因為一旦資料有變則快取失效。且因為查詢快取會跟蹤所有表的變化,它也會成為整個資料庫的瓶頸(資源競爭點)

設定:query_cache_size = 0,同時配合設定query_cache_type = 0,MySQL5.7.20以上、MySQL8.0會直接棄用所有查詢快取配置項

max_connections = xxx

解讀:最大連線數,當max_connections設定太小時(預設151),MySQL可能會報錯Too many connections。當max_connections設定太大時(1000以上),作業系統可能忙於執行緒間的切換而失去響應

設定:每個連線都會消耗一定記憶體,計算過程如下:

# 計算
mysql> SELECT CONCAT(ROUND(SUM(VARIABLE_VALUE)/(1024*1024)),'M') AS 'per_connection' 
       FROM performance_schema.global_variables 
       WHERE VARIABLE_NAME IN ('read_buffer_size', 'read_rnd_buffer_size', 'sort_buffer_size', 
       'join_buffer_size', 'thread_stack', 'max_allowed_packet', 'net_buffer_length');  
       
+----------------+
| per_connection |
+----------------+
| 17M            |
+----------------+

# 連線
mysql> SHOW STATUS LIKE 'threads_connected'; 
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Threads_connected | 99    |
+-------------------+-------+

# 記憶體
$ top -c|grep mysqld
PID    USER   PR  NI VIRT     RES    SHR  S  %CPU  %MEM TIME+     COMMAND
24411  mysql  20  0  8327348  6.458g 7680 S  36.7  85.4 831:56.14 /usr/sbin/mysqld --daemonize ...

# 校驗
5 + 17 * 99 / 1024 = 6.64g,其中innodb_buffer_pool_size設定為5G,
總和6.64g約等於通過top命令顯示的mysqld程序6.458g,
MySQL所佔作業系統記憶體的精確計算與本公式有所出入,但與實際相差甚微,可用於實際生產環境計算
注意:
	1.performance_schema.global_variables 5.7.6版本以後才有此引數

thread_cache_size = xx

解讀:執行緒快取大小,客戶端連線時,MySQL會為每個連線分配一個執行緒,通過設定thread_cache_size = N,MySQL可以重複利用儲存在快取中的N個執行緒,從而改善頻繁的執行緒建立銷燬的開銷。同時,應用如果有連線池複用設定,那也會改善MySQL Server的執行緒開銷

設定:可以通過監控" SHOW STATUS LIKE 'threads_connected' "的數量,確定每天的平均連線數

sync_binlog = x

解讀:二進位制事務日誌刷盤時機,需要配合log-bin選項才能記錄二進位制日誌。區別於InnoDB事務日誌,二進位制事務日誌是針對整個MySQL Server的,而InnoDB事務日誌只針對InnoDB儲存引擎。二進位制事務日誌的作用一是用於主從複製,二是用於資料恢復。區別於InnoDB事務日誌恢復,二進位制事務日誌是用於誤操作的資料恢復,而InnoDB事務日誌是用於InnoDB儲存引擎的崩潰恢復

當0時,將由作業系統控制binlog_cache的刷盤時機
當1時,所有事務開始、提交階段,都會同步寫入磁碟,這是最安全的方式。如果設定innodb_flush_log_at_trx_commit = 1, sync_binlog = 1,這是使用InnoDB事務最安全可靠的方式
當N時,事務每提交N次,同步寫入一次二進位制日誌。
設定:如果MySQL是單機,可以考慮sync_binlog=0;如果是主從,且每秒事務併發量低,考慮sync_binlog=1;事務併發量很高,考慮sync_binlog=N,N的選取可以通過統計業務正常時期的OPS

設定:如果MySQL是單機,可以考慮sync_binlog=0;如果是主從,且每秒事務併發量低,考慮sync_binlog=1;事務併發量很高,考慮sync_binlog=N,N的選取可以通過統計業務正常時期的OPS

- sync_binlog = 0
transaction --> binlog_cache -- 作業系統控制 --> innodb_log_file
- sync_binlog = 1
transaction --> binlog_cache -- 每次提交前後 --> innodb_log_file
- sync_binlog = N
transaction --> binlog_cache -- 每N次提交 --> innodb_log_file