Innodb

在 MYSQL 5.7 中插入單行需要 15 秒(偶爾會發生)

  • September 30, 2020

至少,我在 MYSQL 中看到非常零星的慢查詢,這就是 Datadog 所暗示的問題所在。例如,在過去 48 小時內,我有 726K 跟踪(包括選擇和更新)中有 5 個查詢很慢。它似乎與磁碟延遲的峰值和/或 CPU 被盜有關(但是,盒子上有足夠的備用容量)。我很困惑,我不確定從哪裡開始嘗試尋找修復(或者即使它值得嘗試)

這是 15 秒 COMMIT 的範例。它正在對錶進行一次插入visitors。該表有約 500 萬行和以下結構:

CREATE TABLE `visitors` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `session_id` varchar(255) DEFAULT NULL,
 `market_code` varchar(255) DEFAULT NULL,
 `user_id` int(11) DEFAULT NULL,
 `created_at` datetime DEFAULT NULL,
 `updated_at` datetime DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `index_visitors_on_session_id` (`session_id`)
) ENGINE=InnoDB AUTO_INCREMENT=41764933 DEFAULT CHARSET=utf8;

查詢跟踪

在這個特定範例中,是否可能正在更新索引並導致這種極端峰值?奇怪的是,這些緩慢的更新通常是“集群”(同時會有 4 或 5 個事務到不同的表,這些事務同時很慢)事實上,對於上面過去 48 小時內 5 個慢查詢的範例,它們一切都發生在一秒鐘之內。

歡迎任何關於可能導致這種情況的建議。

下面的慢跡(輪廓)

較慢的“COMMIT”和“BEGIN”用於兩個不同的表,它們都包裝了一個更新由主鍵索引的單行的事務。

在此處輸入圖像描述

更新 1 - 回答查詢

  1. 我在日誌中看到的 iops 或批量傳輸沒有峰值。磁碟延遲和 cpu.iowait 出現峰值(見附件)

在此處輸入圖像描述 2. 我確實啟用了慢查詢日誌。它是巨大的,因為它記錄了太多並且很長時間沒有被清除。我可能需要重新設置它才能很好地使用它——我會調查的。3. 我無權訪問主機,但在 VM 上 Datadog 確實報告了stolencpu,這肯定是 ~ nil(它報告了上個月被盜 cpu < .01%)。

sync_binlog提供者確實建議更改和 的值innodb_flush_log_at_trx_commit。我實際上已經設置innodb_flush_log_at_trx_commit=2好了(如果發生崩潰,我們可以失去幾秒鐘甚至幾分鐘的數據)。我還沒有嘗試改變sync_binlog=0,我需要更多地了解這一點。我想知道這是否有幫助?

更新 2 - 9 個月的磁碟延遲圖表。

我認為這張過去 9 個月的磁碟延遲圖表很有趣。3 月 13 日左右,我們的託管服務提供商 (linode) 環境中的某處似乎發生了一些變化。也許是一個吵鬧的鄰居,也許他們的儲存方式發生了變化。我正在與他們跟進此事,希望它可以解決我們一直看到的問題。雖然該圖只顯示了約 3 毫秒的峰值,但潛在的峰值要高得多。

9 個月的磁碟延遲圖

更新 3 - Wilson Hauck 的值

  • SELECT @@innodb_file_per_table; = 1
  • SELECT @@innodb_io_capacity; = 200
  • 顯示全域狀態,如“%flush%”;刷新值
  • 正常執行時間 - 138437

在周末,我嘗試將其更改sync_binlog為零。我似乎仍然在那裡得到一些奇怪的慢查詢。例如,在慢查詢日誌中,我看到了這個:

SET timestamp=1595871703;
SHOW /*!50000 ENGINE*/ INNODB STATUS;
# Time: 2020-07-27T17:41:43.145667Z
# 
# Query_time: 2.138283  Lock_time: 0.000169 Rows_sent: 1  Rows_examined: 1
SET timestamp=1595871703;
SELECT  `public_codes`.* FROM `public_codes` WHERE `public_codes`.`code` = 'fwreh7x1' LIMIT 1;

再次對應於延遲的峰值。為什麼這樣的查詢時間是 2 秒?

更新 5

所以,我重置了慢查詢日誌。從那以後發生了一件有趣的事情.. datadog例如報告執行 4.43 秒UPDATE documents SET last_browse_path = ? WHERE documents . id = ?(更新主鍵引用的單個非索引列)。但是,我沒有看到慢查詢日誌中列出的內容,我想我應該看到。可能 Datadog 給出了一些虛假的結果?

更新 6 - 顯示創建表結果

請注意,這裡只有 240 萬行,儘管自動增量是這樣說的。很長一段時間,我們的增量值都是 10。

CREATE TABLE `public_codes` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `document_id` int(11) NOT NULL,
 `code` varchar(255) DEFAULT NULL,
 `enabled` tinyint(1) DEFAULT '0',
 `created_at` datetime DEFAULT NULL,
 `updated_at` datetime DEFAULT NULL,
 `collaborative_editing` tinyint(1) NOT NULL DEFAULT '0',
 PRIMARY KEY (`id`),
 UNIQUE KEY `index_public_codes_on_document_id` (`document_id`),
 UNIQUE KEY `index_public_codes_on_public_code` (`code`)
) ENGINE=InnoDB AUTO_INCREMENT=17148900 DEFAULT CHARSET=utf8

更新 7。

供應商正要關閉票並問“還有什麼要補充的嗎?”,所以我說問題仍然存在,以及在 3 月 12 日發生了一些變化但我仍然不知道這很奇怪什麼。當時他們說我們已在 3 月 12 日實時遷移到新的(共享)主機。他們給我們發郵件,不幸的是我們沒有監控收件箱。

我正在等待將數據庫盒遷移到專用主機,因為我懷疑這是一個嘈雜的鄰居問題。一旦我完成了遷移(希望在一兩個星期內),然後我會在此更新票證,假設它解決了問題。

很生氣他們沒有告訴我我第一次問起 3 月 12 日的事.. 仍然,只是希望這能解決問題。

它似乎與磁碟延遲的峰值相關

將有 4 或 5 個事務到不同的表,同時速度很慢

磁碟吞吐量(批量傳輸還是 IOP?)是否也出現了峰值?如果是這樣,那麼它可能只是 IO 爭用的突然過剩。檢查是否有一些令人討厭的查詢正在執行,這些查詢正在掃描大型表/索引或併發臨時增加(即您當時看到使用者活動增加?和/或周圍是否有計劃的維護工作?)

都包裝交易

這裡可能存在鎖定問題,您的更新正在等待其他對受影響的行/頁/表持有讀鎖的事務。這些等待可能一直發生,但僅由於我上一段中的一種可能性而引起注意,或者如果由持有相關鎖的單個(或少量)長時間執行的語句引起,則可能是其本身的問題。

如果您還沒有啟用慢查詢日誌(mariadb、IIRC it 和 mysql 的文件在這方面沒有區別),因為如果在出現明顯問題的同時出現重大問題,這可能會提供進一步的線索。

被盜 CPU

這表示您正在虛擬機中執行,因此如果您在內部找不到充分的理由,可能會有很多額外的外部原因導致性能暫時下降。您是否有權訪問主機以檢查其日誌/指標,還是只有此客人?

建議為您的 my.ini 考慮

$$ mysqld $$部分

innodb-io-capacity=1900  # from 200 to allow higher IOPS for your SSD device

考慮在您的 public_codes 表上執行 ANALYZE 以確保索引是最新的。

我懷疑緩慢的查詢與某種形式的刷新活動發生衝突,導致它需要 2 秒。

引用自:https://dba.stackexchange.com/questions/271329