以前這篇文章MySQL配置基礎簡要說明了MySQL的配置基礎,包括配置文件的位置、配置項的分段、配置變量的生效、以及配置變量和狀態變量的查看,對MySQL的配置有了一個基礎。
如今則會進一步瞭解更多底層原理,搞清楚更多配置的含義和做用。html
本文爲《高性能MySQL》讀書筆記,配合文檔查閱更佳: https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html
InnoDB在每一個事務提交的時候,不會把緩衝池的內容當即刷到磁盤。而是從緩衝池將事務記錄到事務日誌中,輸出日誌(持久化),再由事務日誌完成寫磁盤的操做。
事務日誌會把數據文件的隨機I/O轉換成幾乎順序的I/O,並且把刷新到磁盤的操做轉移到後臺,從而讓查詢更快。
事務日誌有固定的大小,採用環形方式寫(寫到末尾時跳轉到開頭繼續寫)。按期將緩衝池傳來的事務經過日誌方式持久化,再將髒數據刷到磁盤中。mysql
緩衝池 <--> 事務日誌 <--> 磁盤
先將事務變成日誌,寫入磁盤(持久化),再慢慢根據日誌內容寫入磁盤。
事務日誌依賴innodb_log_file_size和innodb_log_files_in_groups這兩個變量。前者聲明每一個日誌文件的大小,後者聲明日誌文件的個數。
InnoDB會使用多個日誌文件做爲循環日誌(1號文件寫完了寫2號,2號寫完了寫1號)sql
默認是50M,2個文件。共100M。建議增大單個文件的大小,仍然使用2個文件。(本文使用MySQL 8.0.21 不一樣版本默認參數可能不一致)
mysql> show variables where variable_name like "%inno%log_file%"; +---------------------------+----------+ | Variable_name | Value | +---------------------------+----------+ | innodb_log_file_size | 52428800 | | innodb_log_files_in_group | 2 | +---------------------------+----------+
事務日誌,將事務寫入日誌文件的時候,也並非直接寫入的,而是使用寫入緩存。先寫入緩存中,再由緩存按期寫入文件。由innodb_log_buffer_size 參數決定使用寫入緩存大小。
如下3個條件,知足任一條件就會刷新緩存到日誌文件中。數據庫
MySQL 8.0.21 默認大小爲16M。因爲最長每1秒會刷新一次寫入緩存,因此這個參數不用設置的過大,只須要超過每秒產生的事務量便可。
mysql> show variables where variable_name like "%inno%log_b%"; +------------------------+----------+ | Variable_name | Value | +------------------------+----------+ | innodb_log_buffer_size | 16777216 | +------------------------+----------+
InnoDB和磁盤的讀寫交互都經過innodb_flush_method來選擇。主要有以下幾種:segmentfault
一、fdatasync():和fsync()相似,可是隻刷新文件數據自己,不包括元數據。並且,這個選項會使用使用雙重緩衝(包括操做系統這一層的緩存)
二、O_DIRECT:依然使用fsync()來刷新文件到磁盤,可是會關閉操做系統緩存,告知操做系統不要緩存且不要預讀。(全部讀寫都直接到達存儲設備,避免雙重緩衝)緩存
這個設置只會影響操做系統,不會影響RAID卡的預讀。
若是使用這個選項,最好使用帶預讀的RAID卡,且打開寫回(write_back)
三、O_DSYNC
這個選項會使全部寫同步,或者說,只有數據確切寫到磁盤後,寫操做纔會返回。
每一個write()或pwrite()操做都會函數完成前將數據同步到磁盤,且這個過程是阻塞的。[而fsync()容許積累寫操做到緩存,再一次性刷新數據。]安全
https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_flush_method
更多可參考: https://www.cnblogs.com/CNty/p/10943626.html
InnoDB I/O配置文檔: https://dev.mysql.com/doc/refman/5.7/en/optimizing-innodb-diskio.html
表空間的本質是一個虛擬文件系統,由多個文件組成。InnoDB用表空間實現了不少功能,不只有存儲表和索引,還有回滾日誌,插入緩存(Insert Buffer),雙寫緩衝(Doublewrite Buffer)等。服務器
可使用以下2個參數來配置表空間。async
下面是一個例子函數
innodb_data_home_dir = /var/lib/mysql/ innodb_data_file_path = ibdata1:1G;ibdata2;1G;ibdata3:1G
PS:innodb_data_home_dir的默認值是空,和MySQL的data
同目錄。
The default value is the MySQL data
directory.(也就是datadir
變量。
mysql> show variables where variable_name like "datadir"; +---------------+-----------------+ | Variable_name | Value | +---------------+-----------------+ | datadir | /var/lib/mysql/ | +---------------+-----------------+ 1 row in set (0.00 sec)
https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_data_home_dir
定製表空間文件時,能夠選擇使用autoextend來讓表空間能夠自動擴展,即便超過了分配的空間。(可是一旦擴展了就很難收縮, 不建議使用extend)
回收空間的惟一辦法就是導出數據、重啓MySQL、重建、再從新導入。(或者說,無法在不從新導入所有數據的前提下給共享表空間瘦身。
innodb_file_per_table 可讓InnoDB爲每張表使用一個文件。另外,即便打開這個選項,依舊會爲回滾日誌和其餘系統數據使用共享表空間(也就是說,這個選項主要是針對業務的表,將其分文件存儲。系統數據仍是使用默認的共享表空間)
注意,使用獨立表空間會致使一個問題,DROP TABLE性能會不好。 可能會致使服務器阻塞。
建議:打開innodb_file_per_table,每一個數據表一個文件。而且關閉共享表空間的自動擴展。
畢竟每一個表一個文件,管理起來仍是好不少。只要沒有大量的小表。再加上DROP TABLE的性能差。換句話說,也就是表數量沒有太大變更+沒有大量小表,就很適合用獨立表空間。
磁盤和InnoDB交互期間,都會先寫入雙寫緩衝,再寫入目標(本質上,雙寫緩衝就是一個最近寫回的頁面的備份拷貝。
因爲InnoDB寫頁面到雙寫緩衝時,是 順序寫入的,因此性能影響並無那麼大。
Disk --> DoubleWrite --> InnoDB 若是寫入到雙寫緩衝時不完整,可是磁盤中一定是有完整數據的。出現問題時可恢復。 若是寫入到InnoDB時不完整,能夠用雙寫緩衝的數據驗證。 InnoDB --> DoubleWrite --> Disk 與上述相似,雙寫緩衝會保證數據可恢復。
可使用innodb_doubewrite來設置爲0來關閉雙寫(這對於備庫比較合適)
max_connect_errors:若是某個主機連續x個鏈接失敗,則會被BAN掉。一旦被BAN,只能命令刷新緩存才能解除。不建議設置的太小,以避免出現全部應用程序被BAN的狀況。
https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_connect_errors
備庫日誌同步寫磁盤相關:
【這3個變量都是動態變量,一旦設置,會當即對全部備庫生效。】
sync_master_info:每有x個事件發生,就將 master.info 向磁盤同步寫一次。【使用fdatasync() 】
https://dev.mysql.com/doc/refman/5.7/en/replication-options-replica.html#sysvar_sync_master_info
sync_relay_log:每有x個事件被寫入relay log,就將 relay log 向磁盤同步寫一次。【使用fdatasync() 】
https://dev.mysql.com/doc/refman/5.7/en/replication-options-replica.html#sysvar_sync_relay_log
sync_relay_log_info:與上一個相似,每x個事件發生後,就將 relay-log.info 向磁盤同步寫一次。
https://dev.mysql.com/doc/refman/5.7/en/replication-options-replica.html#sysvar_sync_relay_log_info
max_connections
更像是緊急剎車,保證數據庫不會由於應用程序鏈接數突增致使自身不堪重負。(保護數據庫自己)當出現問題,致使新建過多新鏈接時,把多餘的錯誤連接拒絕掉,是一種快速、低代價的失敗方式。
這個參數應該設置的足夠高(能夠處理正常狀況下的負載,服務正常運行),其次也要足夠安全(保證能夠登陸上服務器,進行維護操做)
好比,正常狀況下有300鏈接數,那麼這個值必然不能低於300(保證服務正常運行),能夠考慮400~500.
本文主要是對MySQL配置項進行了進一步學習,主要有InnoDB的IO以及Inno表空間配置(共享表空間和獨立表空間的瞭解),還有一些常見的配置、安全相關的配置、以及備庫相關配置。MySQL的配置項不少,很是靈活,有些還能動態生效。因此更須要深刻了解才能更好的使用。這是一個持續的過程。