MySQL 筆記整理(12) --為什麼我的MySQL會“抖”一下?

来源:https://www.cnblogs.com/dogtwo0214/archive/2019/03/27/10595034.html
-Advertisement-
Play Games

筆記記錄自林曉斌(丁奇)老師的《MySQL實戰45講》 (本篇內圖片均來自丁奇老師的講解,如有侵權,請聯繫我刪除) 12) --為什麼我的MySQL會“抖”一下? 斷更了一段時間,因為這幾周實在是太忙了,周末加班兩天那種。。。 有時你會遇到這樣的問題,一條SQL語句,正常執行的時候很快,但是有時候會 ...


筆記記錄自林曉斌(丁奇)老師的《MySQL實戰45講》

(本篇內圖片均來自丁奇老師的講解,如有侵權,請聯繫我刪除)

12) --為什麼我的MySQL會“抖”一下?

  斷更了一段時間,因為這幾周實在是太忙了,周末加班兩天那種。。。

  有時你會遇到這樣的問題,一條SQL語句,正常執行的時候很快,但是有時候會變得特別慢。並且這種場景很難復現,不只隨機而且持續時間很短。這其實與MySQL的臟頁以及它的刷新機制有關。之前我們有過一個關於《孔乙己》裡面酒館老闆記賬的比喻。在這個比喻里,掌柜的賬本就是我們的數據文件,掌柜的臨時寫下的粉板就是我們的日誌文件(redo log),而掌柜的記憶就相當於我們的記憶體。

  粉板可以記錄的內容有限(redo log迴圈寫),掌柜的記憶也是有限的,因此他總要找時間把這兩部分的內容記錄到賬本里去。這個術語就是flush.

  當記憶體數據頁跟磁碟數據頁內容不一致的時候,我們稱這個記憶體頁為“臟頁”。記憶體數據寫入到磁碟後,記憶體和磁碟上的數據頁的內容就一致了,稱為“乾凈頁”。

  大致上有四種情景來進行刷“臟頁”:

  1. 粉板滿了。(redo log寫滿),redo log寫滿以後,如果又有了新的數據,就不得不去除一些之前的數據。當然,在去除之前,要先把正確的數據記錄下來才行。
  2. 生意太好,短時間內有很多客人,掌柜的記不下來了。(系統記憶體不足)。記憶體不足時,需要先淘汰掉一些數據頁,如果這些數據頁中有“臟頁”就必須要把這些記錄到磁碟才行。你可能會有疑問,為什麼不直接淘汰掉這些頁呢,如果再有相關的記錄,就利用redo log來還原數據呢?(掌柜的疑問一部分腦子裡的記憶,下次再有的話,先看賬本,然後再看粉板,倒退出最新的記錄),這其實是從性能方面考慮的。如果我們保證每次刷臟頁一定會寫磁碟,那麼下次再讀的時候就有兩種情況。一是記憶體中有記錄,那麼直接返回。二是,記憶體中沒有,那麼先從磁碟讀,讀到了就直接返回。對應掌柜的就是,掌柜的有印象,直接返回。掌柜的沒有印象查看賬本,找到了就直接返回。
  3. 生意不太忙的時候,掌柜的閑著沒事,就更新賬本。(系統空閑),閑著沒事,Mysql就自己刷臟頁玩。
  4. 年底放假,酒店關門幾天。(MySQL正常關閉),正常關閉時MySQL會把記憶體的臟頁都flush到磁碟上。

  回到我們開始的問題,什麼情況會抖一下呢?首先排除後兩種,空閑或是要關閉資料庫時。來看看前兩種情況:

  先是redo log寫滿了,要flush臟頁,這種情況是InnoDB要儘量避免的。因為這種情況下,整個系統就不能再接受更新了,所有的更新都必須堵住。如果你從監控上看,這時的更新數會跌為0.然後是第二種情況:“記憶體不夠用了,要先將臟頁寫到磁碟”。這種情況是常態。InnoDB用緩衝池(buffer pool)管理記憶體,緩衝池中的記憶體頁有三種狀態:

  1. 還沒使用的
  2. 使用了並且是乾凈頁的
  3. 使用了並且是臟頁的  

  InnoDB的策略是儘量使用記憶體,因此對於一個長時間運行的庫來說,未被使用的頁面很少。當要讀入的數據頁沒有在記憶體的時候,就必須到緩衝池中申請一個數據頁。這時候只能把最久不使用的數據頁從記憶體中淘汰掉。如果淘汰掉的是一個乾凈頁,可以直接釋放出來複用。如果淘汰掉的是一個臟頁,就必須先將臟頁刷到磁碟,變成乾凈頁後才能復用。所以,刷臟頁雖然是常態,但是出現以下兩種情況,都會明顯的影響性能:

  1. 一個查詢要淘汰的臟頁太多,會導致查詢的響應時間明顯變長
  2. 日誌寫滿,更新全部堵住,寫性能跌為0,這個情況對敏感業務來說,是不能接受的。

  所以,InnoDB需要有控制臟頁比例的機制,來儘量避免上面的這兩種情況。

InnoDB刷臟頁的控制策略

  首先,你要正確地告訴InnoDB所在主機的IO能力,這樣InnoDB才能知道需要全力刷臟頁的時候,可以刷多快。這個就要用到innodb_io_capacity這個參數了,它會告訴InnoDB你的磁碟能力。這個值建議你設置為磁碟的IOPS,磁碟的IOPS可以通過fio(linux)來進行測試。(Linux下fio,window下可以使用iometer)

  InnoDB使用兩個因素來進行計算刷盤速度。一個是臟頁比例,一個是redo log的寫盤速度。參數innodb_max_dirty_pages_pct是臟頁比例上限,預設值是75%。InnoDB會根據當前的臟頁比例M,算出一個範圍在0到100之間的數字。InnoDB每次寫入日誌都有一個序號,當前寫入的序號跟checkpoint對應的序號之間的差值,我們假設為N,同樣,InnoDB會根據這個N算出一個0到100之間的數字。N越大這個計算出來的值就越大。然後,根據上述兩個計算出的數據f(M)和f(N),取其中較大的值記為R,之後引擎就可以按照innodb_io_capacity定義的能力乘以R%來控制刷臟頁的速度了。

  因此要合理的設置innodb_io_capacity的值,平時要多關註臟頁的比例,不要讓它經常接近75%。

  還有一個有趣的策略:一旦一個請求涉及到刷臟頁,在準備進行刷臟頁的時候,會把這個數據頁旁邊的數據頁也檢查一下,如果這個鄰居也是臟頁,那麼就會把鄰居一起刷掉。InnoDB使用參數innodb_flush_neighbors參數來控制這個行為,為1的時候就會觸發這個“連坐”機制。在MySQL8.0中,這個預設值已經是0了。

上期問題:

  如果你要維護學生信息的資料庫,學生登錄名統一是"學號@gamail.com",學號的規則是十五位的數字,前三位是城市編號,四到六位是學校編號,七到十位是入學年份,最後五位是順序編號,只考慮登錄驗證的話,你會怎麼設計這個登錄名的索引呢?

  由於這個學號的規則,無論是正向還是反向的首碼索引,重覆度都很高。前三位是城市編號,四到六位是學校編號,這六位數字其實是相對固定的。而郵箱尾碼也是確定的,因此可以只存入學年份加順序編號,它們的長度是9位。在此基礎上,可以用數字類型來存儲這個9位數字,這樣只需占用4個位元組,這其實是一種hash,只是用了最簡單的轉換規則。

  另有別的思路是,一個學校總人數不會很大,這點數據量,這個表必然是個小表。直接存原來的字元串,可以使業務更簡單。這也是一種很好的回答,結合實際業務。

問題:

  一個記憶體配置為128GB,innodb_io_capacity設置為20000的大規格實例,正常會建議你將redo log設置成4個1GB的文件,但是如果你配置時不小心將redo log設置為了4個100M的文件,會發生什麼情況呢?為什麼呢?


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 博客為日常工作學習積累總結: 環境準備: 系統安裝完成後: 1.配置靜態IP 網卡文件:cat /etc/sysconfig/network-scripts/ifcfg-eth0 配置靜態IP代碼如下 重啟網卡: service network restart systemctl restart n ...
  • 硬體環境 ubuntu 16.04LTS + windows10 雙系統 NVIDIA TiTan XP 顯卡(12G) 軟體環境 搜狗輸入法 顯卡驅動:LINUX X64 (AMD64/EM64T) DISPLAY DRIVER (418.56) https://www.nvidia.cn/Dow ...
  • socket socket也稱套接字,網路編程的基礎。一般情況下我不喜歡直接去說socket的函數都是怎麼用的,那個很多人都寫出來了,而且肯定比我好的有的是。 但是今天想寫的是我的理解中,產生socket的原因,我覺得只有瞭解socket的本質、機理,才能更靈活的使用他的API。那樣就會知道為什麼要 ...
  • Linux指令 useradd + 添加用戶 + d 添加用戶路徑 + e 制定密碼有效時間 + G 指定用戶所屬組 passwd + 修改用戶密碼 su + 切換用戶 exit + 退出連接(ssh連接,screen) touch + 新建一個文件 mkdir + 新建一個文件夾 ls + 顯示當 ...
  • mysql 回顧 資料庫的設計必須滿足三範式 1NF: 強調列的原子性,列不可拆分 eg: 一張表(聯繫人) 有(姓名,性別,電話)三列,但是現實中電話又可分為家庭電話和公司電話,這種表結構設計就不符合第一範式了, 正確的應該是繼續拆分(姓名,性別,家庭電話,公司電話) 2NF: 首先滿足1NF,另 ...
  • Linux Mysql資料庫安全配置 目錄: 1.修改mysql管理員賬號root的密碼(2種方法) 2.修改mysql管理員賬號root 3.mysql管理員root賬號密碼遺忘解決辦法(2種方法) 4.創建資料庫用戶(3種方法) 5.mysql資料庫許可權管理 本地許可權 網路許可權 撤銷許可權 刪除用 ...
  • Redis Cluster採用虛擬槽分區,所有的key根據哈希函數映射到0~16383槽內,計算公式: slot = CRC16(key) & 16383 每個節點負責維護一部分槽以及槽所映射的鍵值對。 Redis虛擬槽分區的特點,解耦數據與節點之間的關係,簡化了節點擴容和收縮難度。但其存在如下限制 ...
  • 1.hive概述 Apache Hive數據倉庫軟體有助於使用SQL讀取,編寫和管理駐留在分散式存儲中的大型數據集。可以將結構投影到已存儲的數據中。提供了命令行工具和JDBC驅動以將用戶連接到Hive。 2.hive優缺點 優點: (1)操作介面採用了sql,簡化開發,減少學習成本。 (2)避免手寫 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...