執行個體的 CPU 使用率偏高可能有多種原因,例如工作負載增加、大量交易、查詢速度緩慢和執行時間長的交易。
未充分配置的執行個體推薦工具會分析 CPU 使用率。如果 CPU 使用率在過去 30 天內有相當長的時間達到或超過 95%,推薦工具就會發出警示,並提供其他洞察資料,協助您解決問題。
本文說明如何檢查及改善 Cloud SQL for MySQL 執行個體,如果該執行個體的 CPU 使用率過高,就會由未充分配置的執行個體推薦工具判斷。
建議
CPU 使用率會隨著工作負載成比例增加。如要降低 CPU 使用率,請檢查執行中的查詢並進行最佳化。以下是檢查 CPU 用量的步驟。
查看
Threads_running
和Threads_connected
使用下列查詢,查看執行中的執行緒數量:
> SHOW STATUS like 'Threads_%';
Threads_running
是Threads_connected
的子集。其餘執行緒處於閒置狀態。Threads_running
增加會導致 CPU 用量增加。建議您檢查這些執行緒正在執行的內容。查看查詢狀態
執行
SHOW PROCESSLIST
指令,查看目前的查詢。它會依序傳回所有已連結的執行緒,以及這些執行緒正在執行的 SQL 陳述式。mysql> SHOW [FULL] PROCESSLIST;
請留意狀態和時間長度欄。檢查是否有許多查詢卡在相同狀態。
- 如果許多執行緒顯示
Updating
,可能會發生記錄鎖定爭用情形。請參閱下一個步驟。 - 如果許多執行緒都顯示資料表中繼資料鎖定的
Waiting
,請檢查查詢以瞭解資料表,然後尋找可能保留中繼資料鎖定的 DDL (例如ALTER TABLE
)。如果早期查詢 (例如長時間執行的SELECT query
) 正在保留資料表中繼資料鎖定,DDL 也可能會等待資料表中繼資料鎖定。
- 如果許多執行緒顯示
檢查記錄鎖定競爭
當交易鎖定熱門索引記錄時,會阻止其他交易要求相同的鎖定。這可能會導致連鎖效應,導致許多要求卡住,並增加
Threads_running
的值。如要診斷鎖定爭用情形,請使用information_schema.innodb_lock_waits
表格。以下查詢會列出每筆封鎖交易,以及相關封鎖交易的數量。
SELECT t.trx_id, t.trx_state, t.trx_started, COUNT(distinct w.requesting_trx_id) AS blocked_trxs FROM information_schema.innodb_lock_waits w INNER JOIN information_schema.innodb_trx t ON t.trx_id = w.blocking_trx_id GROUP BY t.trx_id,t.trx_state, t.trx_started ORDER BY t.trx_id;
單一大型 DML 和許多並行的 DML 都可能會導致列鎖競爭。您可以透過下列步驟,從應用程式端進行最佳化:
- 避免長時間交易,因為資料列鎖定會保留到交易結束為止。
- 將單一大型 DML 分割成小型 DML。
- 將單一資料列 DML 分批處理成小型區塊。
- 盡量減少執行緒之間的爭用情形;舉例來說,如果應用程式程式碼使用連線集區,請將 ID 範圍指派給同一個執行緒。
找出長時間執行的交易
使用
SHOW ENGINE INNODB STATUS
在「交易」部分,您可以看到所有未結交易,並以最早到最舊的順序排列。
mysql> SHOW ENGINE INNODB STATUS\G …… ------------ TRANSACTIONS ------------ … ---TRANSACTION 245762, ACTIVE 262 sec 2 lock struct(s), heap size 1136, 1 row lock(s), undo log entries 1 MySQL thread id 9210, OS thread handle 140262286128896, query id 202218 localhost root
請從最早的交易開始,找出下列問題的答案:
- 這些交易執行多久了?
- 有多少個鎖定結構體和列鎖定項目?
- 有多少個復原記錄項目?
- 連線主機和使用者是什麼?
- 持續查詢的 SQL 陳述式為何?
使用
information_schema.innodb_trx
如果
SHOW ENGINE INNODB STATUS
遭到截斷,則另一種檢查所有未結交易的方法是使用information_schema.innodb_trx
資料表:SELECT trx_id, trx_state, timestampdiff(second, trx_started, now()) AS active_secs, timestampdiff(second, trx_wait_started, now()) AS wait_secs, trx_tables_in_use, trx_tables_locked, trx_lock_structs, trx_rows_locked, trx_rows_modified, trx_query FROM information_schema.innodb_trx
如果交易顯示目前執行時間較長的陳述式,您可以選擇停止這些交易以減輕伺服器的壓力,或是等待重要交易完成。如果較舊的交易記錄沒有顯示任何活動,請繼續執行下一個步驟,找出交易記錄。
檢查長時間執行交易的 SQL 陳述式
使用
performance_schema
如要使用
performance_schema
,您必須先開啟該功能。這項變更需要重新啟動執行個體。performance_schema
開啟後,請確認是否已啟用檢測工具和取用者:SELECT * FROM setup_consumers where name like 'events_statements_history'; SELECT * FROM setup_instruments where name like 'statement/sql/%';
如果尚未啟用,請按照下列步驟操作:
UPDATE setup_instruments SET ENABLED = 'YES', timed = 'YES' WHERE NAME LIKE 'statement/%'; UPDATE setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE 'events_statements%';
根據預設,每個執行緒都會保留
performance_schema_events_statements_history_size
定義的最後 10 個事件。這些資訊通常足以在應用程式程式碼中找出交易。此參數不是動態參數。使用
mysql thread id
(即processlist_id
) 查詢記錄事件:SELECT t.thread_id, event_name, sql_text, rows_affected, rows_examined, processlist_id, processlist_time, processlist_state FROM events_statements_history h INNER JOIN threads t ON h.thread_id = t.thread_id WHERE processlist_id = <mysql thread id> ORDER BY event_id;
使用慢速查詢記錄
為了進行偵錯,您可以將花費超過
N
秒的所有查詢記錄到慢速查詢記錄中。如要啟用慢速查詢記錄,請在Google Cloud 主控台或gcloud CLI
的執行個體頁面中編輯執行個體設定,然後在Google Cloud 主控台或gloud CLI
中使用記錄檢視器查看記錄。
檢查信號量爭用
在並行環境中,共用資源的互斥鎖和讀/寫鎖定可能會成為爭用點,導致伺服器效能變慢。此外,如果訊號量化器的等待時間超過 600 秒,系統可能會當機,以便擺脫停滯狀態。
如要查看信號量爭用情形,請使用下列指令:
mysql> SHOW ENGINE INNODB STATUS\G ---------- SEMAPHORES ---------- ... --Thread 140396021667584 has waited at row0purge.cc line 862 for 241.00 seconds the semaphore: S-lock on RW-latch at 0x30c03e8 created in file dict0dict.cc line 1183 a writer (thread id 140395996489472) has reserved it in mode exclusive number of readers 0, waiters flag 1, lock_word: 0 Last time read locked in file row0purge.cc line 862 Last time write locked in file /build/mysql-5.7-FFKPr6/mysql-5.7-5.7.22/storage/innobase/dict/dict0stats.cc line 2376 ...
每個信號量等待作業中,第一行會顯示等待中的執行緒、特定信號量,以及等待時間長度。如果重複執行
SHOW ENGINE INNODB STATUS
時經常出現信號量等待,尤其是等待時間超過幾秒,表示系統正在執行並行處理瓶頸。不同工作負載和設定會有不同的競爭點。
如果信號機經常位於 btr0sea.c,則自適應雜湊索引可能就是爭用的原因。請嘗試使用 Google Cloud 控制台或
gcloud CLI
停用該功能。最佳化長
SELECT
查詢首先,請查看查詢。找出查詢的目標,以及取得結果的最佳方式。最佳查詢計畫是盡量減少資料存取次數的計畫。
- 檢查查詢執行計畫:
mysql> EXPLAIN <the query>;
請參閱 MySQL 說明文件,瞭解如何解讀輸出內容並評估查詢效率。
- 使用正確的索引
檢查索引鍵欄,看看是否使用預期的索引。如果不是,請更新索引統計資料:
mysql> analyze table <table_name>
增加用於計算索引統計資料的網頁樣本數量。詳情請參閱 MySQL 說明文件。
- 充分運用索引
使用多欄索引時,請檢查
key_len
欄,瞭解是否充分運用索引來篩選記錄。最左欄必須是相等比較,且索引可用於第一個範圍條件,包括該條件在內。- 使用最佳化器提示
另一種確保正確索引的方法,是使用索引提示和資料表彙整順序的提示。
避免使用 READ COMMITTED 產生長長的記錄清單
記錄清單是指還原資料表空間中未清除的交易清單。交易的預設隔離等級為
REPEATABLE READ
,這會要求交易在整個期間內讀取相同的快照。因此,SELECT
查詢會阻斷清除自查詢 (或交易) 開始以來所建立的復原記錄。因此,長的記錄清單會降低查詢效能。如要避免建立長的記錄清單,您可以將交易隔離層級變更為READ COMMITTED
。有了READ COMMITTED
,您就不需要再保留瀏覽記錄清單,以便提供一致的讀取檢視畫面。您可以為所有工作階段、單一工作階段或下一個單一交易,在全球變更交易隔離層級。詳情請參閱 MySQL 說明文件。調整伺服器設定
伺服器設定有很多種方式。雖然完整的情況超出本文的範圍,但值得一提的是,伺服器也會回報各種狀態變數,提供相關設定的相關資訊。例如:
- 如果
Threads_created/Connections
很大,請調整thread_cache_size
。適當的執行緒快取可縮短執行緒建立時間,並協助處理高並行工作負載。 - 如果
Table_open_cache_misses/Table_open_cache_hits
並非瑣事,請調整table_open_cache
。在資料表快取中加入資料表可節省查詢執行時間,並在高並行環境中產生差異。
- 如果
結束不必要的連線
如果查詢似乎無效或不再需要,您可以停止查詢。如要瞭解如何識別及結束 MySQL 執行緒,請參閱「管理資料庫連線」。
最後,如果 CPU 使用率仍偏高,且查詢形成必要流量,建議您考慮增加執行個體的 CPU 資源,以免資料庫發生當機或停機情形。