MySQL配置再學習

一、簡介

以前這篇文章MySQL配置基礎簡要說明了MySQL的配置基礎,包括配置文件的位置、配置項的分段、配置變量的生效、以及配置變量和狀態變量的查看,對MySQL的配置有了一個基礎。
如今則會進一步瞭解更多底層原理,搞清楚更多配置的含義和做用。html

本文爲《高性能MySQL》讀書筆記,配合文檔查閱更佳: https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html

二、InnoDB IO配置

2.一、InnoDB 事務日誌:

InnoDB在每一個事務提交的時候,不會把緩衝池的內容當即刷到磁盤。而是從緩衝池將事務記錄到事務日誌中,輸出日誌(持久化),再由事務日誌完成寫磁盤的操做。
事務日誌會把數據文件的隨機I/O轉換成幾乎順序的I/O,並且把刷新到磁盤的操做轉移到後臺,從而讓查詢更快。
事務日誌有固定的大小,採用環形方式寫(寫到末尾時跳轉到開頭繼續寫)。按期將緩衝池傳來的事務經過日誌方式持久化,再將髒數據刷到磁盤中。mysql

緩衝池 <--> 事務日誌 <--> 磁盤
先將事務變成日誌,寫入磁盤(持久化),再慢慢根據日誌內容寫入磁盤。

2.二、事務日誌的配置:

事務日誌依賴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        |
+---------------------------+----------+

2.三、事務日誌自己的寫入緩存:

事務日誌,將事務寫入日誌文件的時候,也並非直接寫入的,而是使用寫入緩存。先寫入緩存中,再由緩存按期寫入文件。由innodb_log_buffer_size 參數決定使用寫入緩存大小。
如下3個條件,知足任一條件就會刷新緩存到日誌文件中。數據庫

  • 每隔1秒
  • 寫入緩存滿
  • 有事務提交
MySQL 8.0.21 默認大小爲16M。因爲最長每1秒會刷新一次寫入緩存,因此這個參數不用設置的過大,只須要超過每秒產生的事務量便可。
mysql> show variables where variable_name like "%inno%log_b%";
+------------------------+----------+
| Variable_name          | Value    |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+

2.四、InnoDB和文件系統的交互方式

InnoDB和磁盤的讀寫交互都經過innodb_flush_method來選擇。主要有以下幾種:segmentfault

  • fdatasync
  • O_DIRECT
  • O_DSYNC

一、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 表空間配置

3.一、InnoDB表空間簡介:

表空間的本質是一個虛擬文件系統,由多個文件組成。InnoDB用表空間實現了不少功能,不只有存儲表索引,還有回滾日誌,插入緩存(Insert Buffer),雙寫緩衝(Doublewrite Buffer)等。服務器

3.二、基礎配置:

可使用以下2個參數來配置表空間。async

  • innodb_data_home_dir:表空間文件存儲位置。
  • innodb_data_file_path:定製表空間文件的名稱大小等。

下面是一個例子函數

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、重建、再從新導入。(或者說,無法在不從新導入所有數據的前提下給共享表空間瘦身。

3.三、共享表空間與獨立表空間

innodb_file_per_table 可讓InnoDB爲每張表使用一個文件。另外,即便打開這個選項,依舊會爲回滾日誌和其餘系統數據使用共享表空間(也就是說,這個選項主要是針對業務的表,將其分文件存儲。系統數據仍是使用默認的共享表空間)

注意,使用獨立表空間會致使一個問題,DROP TABLE性能會不好。 可能會致使服務器阻塞。

建議:打開innodb_file_per_table,每一個數據表一個文件。而且關閉共享表空間的自動擴展。

畢竟每一個表一個文件,管理起來仍是好不少。只要沒有大量的小表。再加上DROP TABLE的性能差。換句話說,也就是表數量沒有太大變更+沒有大量小表,就很適合用獨立表空間。

四、雙寫緩衝(DoubleWrite)配置

磁盤和InnoDB交互期間,都會先寫入雙寫緩衝,再寫入目標(本質上,雙寫緩衝就是一個最近寫回的頁面的備份拷貝。

因爲InnoDB寫頁面到雙寫緩衝時,是 順序寫入的,因此性能影響並無那麼大。
Disk --> DoubleWrite --> InnoDB
若是寫入到雙寫緩衝時不完整,可是磁盤中一定是有完整數據的。出現問題時可恢復。
若是寫入到InnoDB時不完整,能夠用雙寫緩衝的數據驗證。
InnoDB --> DoubleWrite --> Disk
與上述相似,雙寫緩衝會保證數據可恢復。

可使用innodb_doubewrite來設置爲0來關閉雙寫(這對於備庫比較合適)

五、安全和穩定配置

  • expire_logs_days:若是使用Binlog就應該打開 ,保存二進制日誌的天數。清理過時的日誌。根據實際狀況,在保證備份的狀況下去配置。(主動聲明的意義在於,避免二進制日誌打滿磁盤,若是有須要,能夠增加保存時間
  • max_allowed_packet:禁止服務器收發過大的數據包。
  • max_connect_errors:若是某個主機連續x個鏈接失敗,則會被BAN掉。一旦被BAN,只能命令刷新緩存才能解除。不建議設置的太小,以避免出現全部應用程序被BAN的狀況。

    https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_connect_errors
  • skip_name_resolve:關閉DNS查找。MySQL在鏈接時,會正向/反向查DNS,確認鏈接主機的主機名,根據實際狀況判斷是否關閉。

六、備庫相關配置

  • read_only:備庫強烈建議開啓只讀,只接受從主庫傳輸過來的變動。
  • skip_slave_start:阻止MySQL自動啓動複製,若是備庫出現問題重啓,絕對不能自動複製,要手動確認檢查後纔可。
  • slave_net_timeout:備庫鏈接主庫失敗時,重連前等待時間.默認60分鐘太長了,建議改成1分鐘或者更短。

備庫日誌同步寫磁盤相關:
【這3個變量都是動態變量,一旦設置,會當即對全部備庫生效。】

七、其餘常見配置

  • tmp_table_size和max_heap_table_size:
    若是隱式內存臨時表超過這兩個設置,則會轉換爲硬盤表。須要關注Created_tmp_disk_tables和Created_tmp_tables,這兩個磁盤臨時表狀態,來確認。
    這兩個參數能夠簡單的配置爲同樣的大小,不建議設置的過大。若是臨時表過大,使用磁盤比使用硬盤好,省得內存溢出。
  • max_connections
    更像是緊急剎車,保證數據庫不會由於應用程序鏈接數突增致使自身不堪重負。(保護數據庫自己)當出現問題,致使新建過多新鏈接時,把多餘的錯誤連接拒絕掉,是一種快速、低代價的失敗方式。
    這個參數應該設置的足夠高(能夠處理正常狀況下的負載,服務正常運行),其次也要足夠安全(保證能夠登陸上服務器,進行維護操做)

    好比,正常狀況下有300鏈接數,那麼這個值必然不能低於300(保證服務正常運行),能夠考慮400~500.
  • Max_used_connections:這個狀態是最高鏈接數的值。同時還有一個Max_used_connections_time,聲明時間。
    你能夠清楚的知道,鏈接數的峯值在何時。
  • thread_cache_size
    線程緩存要根據實際狀態來制定。好比Threads_connected、Threads_created、Threads_cached。
    能夠根據正在鏈接中的線程數來估測緩存大小。若是每秒建立的線程數不少或者每秒建立的線程愈來愈多,那麼就須要增大緩存。有時候,也須要根據已經緩存了的線程數來判斷緩存大小是否合適。
  • table_cache_size
    表緩存建議配置的足夠大,避免須要常常從新打開、從新解析表定義。(若是表不是不少,徹底能夠配置一個大的表緩存,把全部表結構都緩存了。
    相關狀態:Opened_tables,若是已打開的表一直在增加,建議適當增大表緩存。
    值推薦:一、不建議這個值超過10 000。二、建議從鏈接數的10倍開始調整。

小結

本文主要是對MySQL配置項進行了進一步學習,主要有InnoDB的IO以及Inno表空間配置(共享表空間和獨立表空間的瞭解),還有一些常見的配置、安全相關的配置、以及備庫相關配置。MySQL的配置項不少,很是靈活,有些還能動態生效。因此更須要深刻了解才能更好的使用。這是一個持續的過程。

相關文章
相關標籤/搜索