前一篇的部落格對innodb的讀快取做了解讀。
那麼innodb是否只有對讀取做了優化呢?
對於我所從事的網路遊戲業務而言,的確是乙個讀多寫少的場景,但是並不意味著所有場景都是如此。
首先的一點,資料庫需要保證安全性,所以每一次寫入資料庫的時候,都會產生redo log,用來在資料庫崩潰的時候進行回滾,同時,如果開啟了binlog,那麼資料庫也會在每一條sql語句執行之後記錄一條binlog,binlog是直接寫入磁碟的,但是binlog是有自己的機制去管理的,與寫操作的效率無關,這裡可以排除其影響
這裡**的是資料落盤的原理:
我們知道,資料庫擁有讀快取的功能,部分頁會被從磁碟讀到記憶體中來,那麼當乙個頁在記憶體中時,發生了寫操作,這個時候應該如何處理呢?
當要修改的資料頁在記憶體中時,資料庫採用的方式是將資料寫入記憶體中,而不是直接寫入磁碟中,然後再將redo log寫入到磁碟。那麼當這個資料頁被從快取中淘汰的時候,這些「髒資料頁」就會被同步地寫入磁碟,等於是將這期間發生的n次的落盤合併成了一次落盤。因為redo log是落盤的,所以即使資料庫崩潰,快取中的資料頁全部丟失,也可以通過redo log將這些資料頁找回來
(redo log是資料庫用來在崩潰的時候進行資料恢復的日誌,redo log的寫入策略可以通過引數控制,並不一定是每一次寫操作之後立即落盤redo log,在部分引數下,redo log可能是每秒集中寫入一次,也有可能採取其他落盤策略,但是無論採用什麼方式,redo log的量都是不會減少的,與資料寫入的覆蓋性不同,後一條redo log是不會覆蓋前一條的,而是增量形式的,因此寫redo log的操作,等同於是對磁碟某一小塊區域的順序i/o,而不像資料落盤一樣隨機在磁碟裡寫入,需要磁碟在多個地方移動磁頭。所以redo log的落盤是io操作當中消耗較少的一種,比資料直接刷回磁碟要優很多)
那麼當乙個頁不在記憶體中時,發生了寫操作,這個時候應該如何處理呢?
正常思路是將這個頁讀到記憶體中,然後對其進行寫操作,然後再進行一次正常的記憶體寫操作和redo log的磁碟寫操作。但是對於寫多讀少的業務,每一次寫操作不命中記憶體就需要一次磁碟讀操作,這顯然會影響效能。
innodb對這裡的寫入操作進行了優化:寫操作並不會立即寫入到磁碟,而是只記錄緩衝變更,等未來資料從磁碟真正被讀出來的時候,才會將緩衝變更合併到緩衝池裡,這種做法可以有效減少寫操作時候的磁碟讀取,提高資料庫效能,這裡對於資料變更的快取區,就是寫緩衝
寫緩衝等於是將寫操作沒有命中快取的情況轉化為了命中快取的情況,由於redo log依然是按策略落盤的,可以理解為資料是安全的,而寫快取的資料也不是長期保留在快取裡的,資料庫有策略定期將寫快取中的資料寫入磁碟的操作,這裡的寫緩衝寫入策略可以由資料庫引數控制(有的採取定時寫入,有的採取滿則寫入,也有的採取閒時寫入)
注意:當資料庫全都是唯一索引的時候,寫緩衝是沒有辦法工作的,因為不將所有資料都讀出來,沒有辦法判斷這次寫操作是否合法,是否符合唯一索引的條件
innodb_change_buffering:配置使用寫緩衝的操作型別,可選all、none、update、deletes等
mysql 快取設定 mysql快取設定
伺服器端的設定 mysql優化首先要知道mysql快取是如何工作以及如何設定,下面是我從別人部落格上覆制過來了,初學者。mysql每個表都可以表示為磁碟上的乙個檔案,必須先開啟,後讀取。為了加快從檔案中讀取資料的過程,mysqld 對這些開啟檔案進行了快取,其最大數目由 etc mysqld.con...
mysql 快取 mysql 快取機制解讀
首先講解一下,快取的原理 快取存在乙個hash表中,通過查詢sql,查詢資料庫,客戶端協議等作為key,在判斷命中前,命中條件 1 mysql不會解析sql,而是使用sql去查詢快取,2 sql上的任何字元的不同,如空格,注釋,都會導致快取不命中。3 如果查詢有不確定的資料like now curr...
mysql 快取策略 Mysql的快取機制
參考 mysql的快取功能 對於乙個並沒有那麼複雜的系統,但是某幾個表特別大的時候,快取是乙個很實用的乙個功能,是sql優化和查詢提速的常用操作,開啟mysql自帶的此功能,實現查詢結果快取的同時,快取失效的維護由資料庫自己完成,而不像一般的spring框架要通過 或者過期自動超時來維護。當然,這個...