簡體   English   中英

MariaDB下更新、刪除、插入查詢慢

[英]Slow Update, Delete and Insert Queries under MariaDB

我們的服務器已從 Ubuntu 16 更新為 Ubuntu 20 和 MariaDB。不幸的是,網站的加載時間變慢了。 通常 MariaDB 應該比 Mysql 快。我發現,很簡單,網站上的更新命令有時需要大約 7 秒。 但是,如果我通過 myphpadmin 將這些更新命令直接輸入到數據庫中,它們只需要 0.0005 毫秒。

在我看來,MariaDB 經常出現更新命令時出現問題。 mysql 從來都不是問題。這是一個查詢示例:

UPDATE LOW_PRIORITY users
SET user_video_count = user_video_count + 1
WHERE user_id = 12345

數據庫格式為 MyISAM。

我不知道可能是什么原因。 你?

非常感謝你。

它可能像SELECTusers中搜索某些內容一樣簡單。 注意,InnoDB 不會遇到這個問題。

MyISAM在執行UPDATEINSERTDELETE時必然會鎖定表 (還有ALTER和其他 DDL 語句。)如果有很多連接在執行寫入甚至SELECTs的任何混合操作,那么鎖會級聯很長時間。

真正的解決方案,無論是在 MariaDB 還是 [尤其是] 在 MySQL 中,都是切換到 InnoDB。

如果這是對“喜歡”或“觀看次數”進行大量計數的情況,則部分解決方案(在任一引擎中)是將此類計數器放在一個單獨的並行表中。 這避免了那些簡單快速的更新與主表上的其他操作發生沖突。 在人流量極高的區域,收集此類增量並分批應用它們是有必要的。 我認為您的卷不需要那種激進的解決方案。

MySQL 幾乎消除了 MyISAM。 MariaDB 可能會在幾年后效仿。

為了解決這個問題:

myphpadmin 中的相同查詢非常快

問題不在於你如何運行它,而在於同時發生的其他事情。

LOW PRIORITY是 MyISAM 特定的 kludge,有時會起作用。)

MyISAM 進行“表鎖定”; InnoDB 做“行鎖定”。 因此,Innodb 可以在表上執行許多“同時”操作,而 MyISAM 會在寫入發生時立即序列化。

更多(現在專注於 InnoDB。)

可能涉及到的其他一些事情。

如果兩個UPDATEs試圖同時修改同一行,一個將不得不等待(由於行鎖定)。

如果確實有大量事情在發生,延遲可能會一連串地發生。 如果在一個實例中有 20 個連接正在運行,那么它們各自都會減慢彼此的速度。 每個連接都被公平分配,但這意味着它們都變慢了。

SHOW PROCESSLIST查看正在運行的程序——而不是“睡眠”。 “時間”最長的進程(系統線程除外)很可能是這場爭吵的始作俑者。

slowlog 可以幫助更深入地研究。 我打開它,使用足夠低的long_query_time並等待“事件”發生。 然后我使用pt-query-digest (或mydumpslow -st )找出最慢的查詢。 通過更多的努力,人們可能會注意到有很多查詢在某一瞬間“緩慢”——甚至可能是“點查詢”(如UPDATE... WHERE id=constant )意外地比long_query_time運行得慢。 這表示太多查詢和/或某些意外鎖定行的查詢。 (注意:查詢的“時間戳”是查詢結束的時間;減去Query_time即可開始。) SlowLog

更多的

正如您所發現的, innodb_flush_log_at_trx_commit = 2在快速執行大量單查詢事務時是一個很好的修復。 如果該修復的頻率變得太大,那么我上面的評論可能就變得必要了。

=2 和 =0 之間不會有太大的性能差異。

至於innodb_flush_log_at_timeout 請提供 `SHOW GLOBAL STATUS LIKE 'Binlog%commits'

至於innodb_lock_wait_timeout ...我不認為改變它會對你有幫助。 如果您的查詢之一由於該超時而中止,您應該記錄它發生並重試事務。

聽起來您正在使用autocommit = ON運行並且不使用顯式事務? 這很好(對於非金錢活動)。 在某些情況下,使用事務可以提高性能——例如人為地將多個查詢批處理在一起以避免某些 I/O。 缺點是與其他連接發生沖突的可能性增加。 盡管如此,如果您總是檢查錯誤並重新運行“事務”,那么一切都應該很好。

innodb_flush_log_at_trx_commit

當該設置為“1”(可能是您最初的設置)時,每個更新都會額外寫入磁盤以確保數據完整性。 如果磁盤是 HDD(而不是 SDD),則每次更新會增加大約 10 毫秒,因此導致每秒大約 100 次更新的最大值。 有幾種解決方法。

  • innodb_flush_log_at_trx_commit = 0 or 2 ,犧牲一些數據完整性。
  • 人為地將多個更新合並到一個事務中,從而將 10 毫秒分散到多個查詢中。
  • 根據他們正在做什么和/或他們接觸的行明確地組合幾個更新。 (在真正繁忙的系統中,這可能涉及其他服務器和/或其他表。)
  • 將計數器移動到另一個表(見上文)——這允許來自主表上更耗時的操作的干擾。 (我沒有聽到一個明確的例子,但 slowlog 可能已經指出了這一點。)
  • 切換到 SSD 驅動器——更新容量可能增加 10 倍。

我懷疑社交媒體巨頭會做上述所有事情。

當您使用 MariaDB 時,您可以使用像 EverSQL 這樣的工具來查找丟失的索引或發現冗余索引(例如,您在 user_video_count 上有一個您並不真正需要的索引)

首先我要感謝所有幫助過我的人。 我真的很感激人們嘗試投入寶貴的時間。

我想告訴您我是如何設法解決更新、插入和刪除查詢緩慢的問題的。

我將此值添加到 my.cnf 文件中:

innodb_flush_log_at_trx_commit = 2

在我重啟 mysql 服務器后,服務器負載突然下降,更新、插入和刪除查詢也從大約 0.22222 - 0.91922 秒下降到負載下的 0.000013 秒。 就像之前使用 Myisam 和 Mysql 一樣,以及它應該如何使用索引進行如此簡單的更新。

我不得不提一下,我已經將所有接收頻繁插入或更新命令的表設置為 INNODB,將那些有很多選擇的表設置為 ARIA。

由於我們不處理貨幣交易,如果我們因為以下原因而損失最后幾秒對我來說不是問題

innodb_flush_log_at_trx_commit = 2 

我go更進一步。 如果我們輸掉了最后 30 秒,我也可以接受。

所以我也設置了:

innodb_flush_log_at_timeout = 30

我目前正在測試

innodb_flush_log_at_trx_commit = 0

但到目前為止,我沒有看到明顯的改善

innodb_flush_log_at_timeout = 30
innodb_flush_log_at_trx_commit = 0

代替

innodb_flush_log_at_timeout = 1 (default)
innodb_flush_log_at_trx_commit = 2

所以主要目標是:

innodb_flush_log_at_trx_commit = 2

or

innodb_flush_log_at_trx_commit = 0

有誰知道,為什么:

innodb_flush_log_at_timeout = 30
innodb_flush_log_at_trx_commit = 0

並不比剛才快

innodb_flush_log_at_trx_commit = 2

我也不明白,為什么這個設置沒有更受歡迎,因為如果許多網站不介意失去一秒鍾或更多時間,他們可以在速度方面有很大的改進。

非常感謝你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM