當MySQL實例啓動時,數據庫會先去讀一個配置參數文件,用來尋找數據庫的各類文件所在位置以及指定某些初始化參數,這些參數一般定義了某種內存結構有多大等。在默認狀況下,MySQL實例會按照必定的順序在指定的位置進行讀取,用戶只需經過命令mysql --help | grep my.cnf來尋找便可。mysql
簡單地說,能夠把數據庫參數當作一個鍵/值(key/value)對。能夠經過命令SHOWVARIABLES查看數據庫中的全部參數,也能夠經過LIKE來過濾參數名。從MySQL5.1版本開始,還能夠經過information_schema架構下的GLOBAL_VARIABLES視圖來進行查找。sql
MySQL數據庫中的參數能夠分爲兩類:動態(dynamic)參數和靜態(static)參數。動態參數意味着能夠在MySQL實例運行中進行更改,靜態參數說明在整個實例生命週期內都不得進行更改,就好像是隻讀(read only)的。數據庫
能夠經過SET命令對動態的參數值進行修改,global和session關鍵字代表該參數的修改是基於當前會話仍是整個實例的生命週期。有些動態參數只能在會話中進行修改,如autocommit;而有些參數修改完後,在整個實例生命週期中都會生效,如binlog_cache_size;而有些參數既能夠在會話中又能夠在整個實例的生命週期內生效,如read_buffer_size。緩存
須要注意的是,對變量的全局值進行了修改,在此次的實例生命週期內都有效,但MySQL實例自己並不會對參數文件中的該值進行修改。也就是說,在下次啓動時MySQL實例仍是會讀取參數文件。若想在數據庫實例下一次啓動時該參數仍是保留爲當前修改的值,那麼用戶必須去修改參數文件。要想知道MySQL全部動態變量的可修改範圍,能夠參考MySQL官方手冊的DynamicSystem Variables的相關內容。服務器
注:在mysql8中,能夠經過set persist命令來持久化對全局變量的修改。網絡
錯誤日誌文件對MySQL的啓動、運行、關閉過程進行了記錄。MySQL DBA在遇到問題時應該首先查看該文件以便定位問題。該文件不只記錄了全部的錯誤信息,也記錄一些警告信息或正確的信息。用戶能夠經過命令SHOW VARIABLES LIKE'log_error'來定位該文件。session
慢查詢日誌(slow log)可幫助DBA定位可能存在問題的SQL語句,從而進行SQL語句層面的優化。例如,能夠在MySQL啓動時設一個閾值,將運行時間超過該值的全部SQL語句都記錄到慢查詢日誌文件中。DBA天天或每過一段時間對其進行檢查,確認是否有SQL語句須要進行優化。架構
有關慢查詢的一些配置項以下:併發
查詢日誌記錄了全部對MySQL數據庫請求的信息,不管這些請求是否獲得了正確的執行。默認文件名爲:主機名.log,從MySQL 5.1開始,能夠將查詢日誌的記錄放入mysql架構下的general_log表中。異步
二進制日誌(binary log)記錄了對MySQL數據庫執行更改的全部操做,可是不包括SELECT和SHOW這類操做,由於這類操做對數據自己並無修改。
若是用戶想記錄SELECT和SHOW操做,那隻能使用查詢日誌,而不是二進制日誌。此外,二進制日誌還包括了執行數據庫更改操做的時間等其餘額外信息。總的來講,二進制日誌主要有如下幾種做用:
經過配置參數log-bin[=name]能夠啓動二進制日誌。若是不指定name,則默認二進制日誌文件名爲主機名,後綴名爲二進制日誌的序列號,所在路徑爲數據庫所在目錄(datadir)。
如下配置文件參數影響着二進制日誌記錄的信息和行爲:
參數max_binlog_size指定了單個二進制日誌文件的最大值,若是超過該值,則產生新的二進制日誌文件,後綴名+1,並記錄到.index文件。
當使用事務的表存儲引擎(如InnoDB存儲引擎)時,全部未提交(uncommitted)的二進制日誌會被記錄到一個緩存中去,等該事務提交(committed)時直接將緩衝中的二進制日誌寫入二進制日誌文件,而該緩衝的大小由binlog_cache_size決定,默認大小爲32K。此外,binlog_cache_size是基於會話(session)的,也就是說,當一個線程開始一個事務時,MySQL會自動分配一個大小爲binlog_cache_size的緩存,所以該值的設置須要至關當心,不能設置過大。當一個事務的記錄大於設定的binlog_cache_size時,MySQL會把緩衝中的日誌寫入一個臨時文件中,所以該值又不能設得過小。經過SHOW GLOBALSTATUS命令查看binlog_cache_use、binlog_cache_disk_use的狀態,能夠判斷當前binlog_cache_size的設置是否合適。binlog_cache_use記錄了使用緩衝寫二進制日誌的次數,binlog_cache_disk_use記錄了使用臨時文件寫二進制日誌的次數。
在默認狀況下,二進制日誌並非在每次寫的時候同步到磁盤(用戶能夠理解爲緩衝寫)。所以,當數據庫所在操做系統發生宕機時,可能會有最後一部分數據沒有寫入二進制日誌文件中,這會給恢復和複製帶來問題。參數sync_binlog=[N]表示每寫緩衝多少次就同步到磁盤。若是將N設爲1,即sync_binlog=1表示採用同步寫磁盤的方式來寫二進制日誌,這時寫操做不使用操做系統的緩衝來寫二進制日誌。sync_binlog的默認值爲0,若是使用InnoDB存儲引擎進行復制,而且想獲得最大的高可用性,建議將該值設爲ON。
可是,即便將sync_binlog設爲1,仍是會有一種狀況致使問題的發生。當使用InnoDB存儲引擎時,在一個事務發出COMMIT動做以前,因爲sync_binlog爲1,所以會將二進制日誌當即寫入磁盤。若是這時已經寫入了二進制日誌,可是提交尚未發生,而且此時發生了宕機,那麼在MySQL數據庫下次啓動時,因爲COMMIT操做並無發生,這個事務會被回滾掉。可是二進制日誌已經記錄了該事務信息,不能被回滾。這個問題能夠經過將參數innodb_support_xa設爲1來解決,雖然innodb_support_xa與XA事務有關,但它同時也確保了二進制日誌和InnoDB存儲引擎數據文件的同步。
注:二進制日誌的寫入時機是事務語句完成的時候,此時還未真正執行commit和釋放鎖。
Binary logging is done immediately after a statement or transaction completes but before any locks are released or any commit is done. This ensures that the log is logged in commit order.
參數binlog-do-db和binlog-ignore-db表示須要寫入或忽略寫入哪些庫的日誌。默認爲空,表示須要同步全部庫的日誌到二進制日誌。
若是當前數據庫是複製中的slave角色,則它不會將從master取得並執行的二進制日誌寫入本身的二進制日誌文件中去。若是須要寫入,要設置log-slave-update。若是須要搭建master=>slave=>slave架構的複製,則必須設置該參數。
binlog_format參數十分重要,它影響了記錄二進制日誌的格式。在MySQL 5.1版本以前,沒有這個參數。全部二進制文件的格式都是基於SQL語句(statement)級別的,所以基於這個格式的二進制日誌文件的複製(Replication)和Oracle的邏輯Standby有點類似。同時,對於複製是有必定要求的。如在主服務器運行rand、uuid等函數,又或者使用觸發器等操做,這些均可能會致使主從服務器上表中數據的不一致(not sync)。另外一個影響是,會發現InnoDB存儲引擎的默認事務隔離級別是REPEATABLE READ。這其實也是由於二進制日誌文件格式的關係,若是使用READ COMMITTED的事務隔離級別(大多數數據庫,如Oracle,Microsoft SQL Server數據庫的默認隔離級別),會出現相似丟失更新的現象,從而出現主從數據庫上的數據不一致。
MySQL 5.1開始引入了binlog_format參數,該參數可設的值有STATEMENT、ROW和MIXED。
1)表的存儲引擎爲NDB,這時對錶的DML操做都會以ROW格式記錄。
2)使用了UUID()、USER()、CURRENT_USER()、FOUND_ROWS()、ROW_COUNT()等不肯定函數。
3)使用了INSERT DELAY語句。
4)使用了用戶定義函數(UDF)。
5)使用了臨時表(temporary table)。
在一般狀況下,咱們將參數binlog_format設置爲ROW,這能夠爲數據庫的恢復和複製帶來更好的可靠性。可是不能忽略的一點是,這會帶來二進制文件大小的增長,有些語句下的ROW格式可能須要更大的容量。而因爲複製是採用傳輸二進制日誌方式實現的,所以複製的網絡開銷也有所增長。
二進制日誌文件不能像錯誤日誌文件、慢查詢日誌文件那樣用cat、head、tail等命令來查看。要查看二進制日誌文件的內容,必須經過MySQL提供的工具mysqlbinlog。
InnoDB採用將存儲的數據按表空間(tablespace)進行存放的設計。在默認配置下會有一個初始大小爲10MB,名爲ibdata1的文件。該文件就是默認的表空間文件(tablespace file),用戶能夠經過參數innodb_data_file_path對其進行設置,用戶能夠經過多個文件組成一個表空間,同時制定文件的屬性,如:
[mysqld] innodb_data_file_path = /db/ibdata1:2000M;/dr2/db/ibdata2:2000M:autoextend
這裏將/db/ibdata1和/dr2/db/ibdata2兩個文件用來組成表空間。若這兩個文件位於不一樣的磁盤上,磁盤的負載可能被平均,所以能夠提升數據庫的總體性能。同時,兩個文件的文件名後都跟了屬性,表示文件idbdata1的大小爲2000MB,文件ibdata2的大小爲2000MB,若是用完了這2000MB,該文件能夠自動增加(autoextend)。
設置innodb_data_file_path參數後,全部基於InnoDB存儲引擎的表的數據都會記錄到該共享表空間中。若設置了參數innodb_file_per_table,則用戶能夠將每一個基於InnoDB存儲引擎的表產生一個獨立表空間。獨立表空間的命名規則爲:表名.ibd。經過這樣的方式,用戶不用將全部數據都存放於默認的表空間中。
須要注意的是,這些單獨的表空間文件僅存儲該表的數據、索引和插入緩衝BITMAP等信息,其他信息仍是存放在默認的表空間中。下圖顯示了InnoDB存儲引擎對於文件的存儲方式:
在默認狀況下,在InnoDB存儲引擎的數據目錄下會有兩個名爲ib_logfile0和ib_logfile1的文件。在MySQL官方手冊中將其稱爲InnoDB存儲引擎的日誌文件,不過更準確的定義應該是重作日誌文件(redo log file)。重作日誌文件對於InnoDB存儲引擎相當重要,它們記錄了對於InnoDB存儲引擎的事務日誌。
當實例或介質失敗(media failure)時,重作日誌文件就能派上用場。例如,數據庫因爲所在主機掉電致使實例失敗,InnoDB存儲引擎會使用重作日誌恢復到掉電前的時刻,以此來保證數據的完整性。
每一個InnoDB存儲引擎至少有1個重作日誌文件組(group),每一個文件組下至少有2個重作日誌文件,如默認的ib_logfile0和ib_logfile1。爲了獲得更高的可靠性,用戶能夠設置多個的鏡像日誌組(mirrored log groups),將不一樣的文件組放在不一樣的磁盤上,以此提升重作日誌的高可用性。在日誌組中每一個重作日誌文件的大小一致,並以循環寫入的方式運行。InnoDB存儲引擎先寫重作日誌文件1,當達到文件的最後時,會切換至重作日誌文件2,再當重作日誌文件2也被寫滿時,會再切換到重作日誌文件1中。
下列參數影響着重作日誌文件的屬性:
參數innodb_log_file_size指定每一個重作日誌文件的大小。在InnoDB1.2.x版本以前,重作日誌文件總的大小不得大於等於4GB,而1.2.x版本將該限制擴大爲了512GB。
參數innodb_log_files_in_group指定了日誌文件組中重作日誌文件的數量,默認爲2。參數innodb_mirrored_log_groups指定了日誌鏡像文件組的數量,默認爲1,表示只有一個日誌文件組,沒有鏡像。若磁盤自己已經作了高可用的方案,如磁盤陣列,那麼能夠不開啓重作日誌鏡像的功能。最後,參數innodb_log_group_home_dir指定了日誌文件組所在路徑,默認爲./,表示在MySQL數據庫的數據目錄下。
重作日誌文件的大小設置對於InnoDB存儲引擎的性能有着很是大的影響。一方面重作日誌文件不能設置得太大,若是設置得很大,在恢復時可能須要很長的時間;另外一方面又不能設置得過小了,不然可能致使一個事務的日誌須要屢次切換重作日誌文件。此外,重作日誌文件過小會致使頻繁地發生async checkpoint,致使性能的抖動。
重作日誌有一個capacity變量,該值表明了最後的檢查點不能超過這個閾值,若是超過則必須將緩衝池(innodb buffer pool)中髒頁列表(flush list)中的部分髒數據頁寫回磁盤,這時會致使用戶線程的阻塞。
一樣是記錄事務日誌,和以前介紹的二進制日誌有什麼區別?
首先,二進制日誌會記錄全部與MySQL數據庫有關的日誌記錄,包括InnoDB、MyISAM、Heap等其餘存儲引擎的日誌。而InnoDB存儲引擎的重作日誌只記錄有關該存儲引擎自己的事務日誌。
其次,記錄的內容不一樣,不管用戶將二進制日誌文件記錄的格式設爲STATEMENT仍是ROW,又或者是MIXED,其記錄的都是關於一個事務的具體操做內容,即該日誌是邏輯日誌。而InnoDB存儲引擎的重作日誌文件記錄的是關於每一個頁(Page)的更改的物理狀況。
此外,寫入的時間也不一樣,二進制日誌文件僅在事務提交前進行提交,即只寫磁盤一次,不論這時該事務多大。而在事務進行的過程當中,卻不斷有重作日誌條目(redo entry)被寫入到重作日誌文件中。
從重作日誌緩衝往磁盤寫入時,是按512個字節,也就是一個扇區的大小進行寫入。由於扇區是寫入的最小單位,所以能夠保證寫入一定是成功的。所以在重作日誌的寫入過程當中不須要有doublewrite。
從日誌緩衝寫入磁盤上的重作日誌文件是按必定條件進行的,主線程中每秒會將重作日誌緩衝寫入磁盤的重作日誌文件中,不論事務是否已經提交。另外一個觸發寫磁盤的過程是由參數innodb_flush_log_at_trx_commit控制,表示在提交(commit)操做時,處理重作日誌的方式。
參數innodb_flush_log_at_trx_commit的有效值有0、一、2。0表明當提交事務時,並不將事務的重作日誌寫入磁盤上的日誌文件,而是等待主線程每秒的刷新。1和2不一樣的地方在於:1表示在執行commit時將重作日誌緩衝同步寫到磁盤,即伴有fsync的調用。2表示將重作日誌異步寫到磁盤,即寫到文件系統的緩存中。所以不能徹底保證在執行commit時確定會寫入重作日誌文件,只是有這個動做發生。
所以爲了保證事務的ACID中的持久性,必須將innodb_flush_log_at_trx_commit設置爲1,也就是每當有事務提交時,就必須確保事務都已經寫入重作日誌文件。那麼當數據庫由於意外發生宕機時,能夠經過重作日誌文件恢復,並保證能夠恢復已經提交的事務。而將重作日誌文件設置爲0或2,都有可能發生恢復時部分事務的丟失。不一樣之處在於,設置爲2時,當MySQL數據庫發生宕機而操做系統及服務器並無發生宕機時,因爲此時未寫入磁盤的事務日誌保存在文件系統緩存中,當恢復時一樣能保證數據不丟失。