第37問:自旋鎖 旋着旋着人就糊塗了

問題

追求 MySQL 的性能時,總據說要調整自旋鎖的參數: innodb_spin_wait_delay 和 innodb_sync_spin_loops,是真的麼?html

實驗

首先咱們要知道自旋鎖的優勢:自旋鎖要上鎖時,若是須要等待其餘線程釋放鎖,那麼:mysql

  • 在等待鎖的過程當中會先線程會先自旋一段時間sql

    • 自旋階段,線程不會放棄 CPU
  • 自旋事後:數據庫

    • 若是能夠獲取鎖了,那麼響應會比較快(自旋沒發生上下文切換)
    • 若是還須要等待鎖,再用更高成本的方式進行鎖等待

innodb_spin_wait_delay 參數決定了自旋階段的長度。如今咱們試着調整 innodb_spin_wait_delay 參數,來測試一下:服務器

先寬油起一個數據庫,此處忽略步驟運維

建個表,放點數據:oop

配置好 performance_schema:性能

檢查一下相關參數:測試

清理 performance_schema 的統計值:spa

來點壓力:

查詢一下鎖等待成本最高的鎖:

能夠看到鎖等待成本最高的是 lock_mutex,是保護 MySQL 鎖系統的鎖

下面咱們來調整一下 innodb_spin_wait_delay,讓自旋的時間變長:

重作一次壓力(記得先清理統計數據),查看統計數據:

能夠看到 lock_mutex 的平均等待時間從 751267 增長到了 1399041。咱們讓自旋階段增長了 10 倍,鎖等待的時間也會隨之增大。

目前的實驗看上去自旋階段越短越好,那麼自旋階段是否是就沒有意義了?固然不會。

你們能夠將 innodb_spin_wait_delay 設置爲 1,再進行測試,隨着自旋階段的減小,鎖等待的時間也會隨之增大(大部分鎖都使用了高成本的方式來進行等待)。

那麼如何選擇自旋的參數呢?咱們建議「不出問題不瞎調」。

在以前的統計數據中,時間的單位是:cycle,根據如下換算表,鎖的平均時間是 1399041 cycle,大概也就 0.5ms(1399041 / 2385353233 = 0.00058 s),佔 SQL 的總體時間很低,能夠不用瞎調。

一個著名的 CPU 問題

自旋階段,MySQL 會調用 CPU 的 PAUSE 指令,既能佔用了 CPU,同時 PAUSE 指令(比起其餘佔用 CPU 的指令)也比較節能。

不過既然佔用了 CPU,那麼就會體如今 CPU 的使用率上。

如今咱們將 innodb_spin_wait_delay 再放大一點比較一下:

能夠看到 CPU 使用率會隨着自旋階段變長而升高

Intel 的 Skylake 系列 CPU,調大了 PAUSE 指令的週期時長。從 10 cycles 調大到 140 cycles(也許是由於讓 PAUSE 週期變長更有利於節能)

相似於今天的實驗,這個指令的調整至關於拉長了自旋階段。

這就致使了在 Skylake 系列 CPU 下,MySQL 的鎖表現和 CPU 佔用率表現都有可能更糟糕。

(推薦文章:https://tech.meituan.com/2020...

小貼士

看到這裏你們是否是開始焦慮了,要準備換 CPU 了?

其實沒必要焦慮,絕大部分狀況下,你們不用追求極致的性能。比起榨取服務器的一點點極限性能,業務稍微調整一下 SQL 取得的收益會 大幾個數量級。

俗話說:業務寫得好,運維回家早。


關於 MySQL 的技術內容,大家還有什麼想知道的嗎?趕忙留言告訴小編吧!

相關文章
相關標籤/搜索