MySQL 崩潰,目前 error.log 文件很大
我在 6 個月前使用 Laravel Forge 在 DigitalOcean 上創建了一個 droplet。兩週前,我們決定是時候升級 droplet 了,我們從 4GB RAM/2CPU 升級到了 16GB RAM/6CPU 的 droplet,幾天前 MySQL 伺服器崩潰了,讓它再次工作的唯一方法是通過重新啟動伺服器(MySQL 使伺服器無響應)。
當我鍵入 htop 以查看程序列表時顯示了一些
/usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysql.pid
(目前顯示了 30 多個類似的條目)。錯誤日誌大於 1GB(是的,我知道!)並顯示此消息數百次:
[Warning] InnoDB: Difficult to find free blocks in the buffer pool (21 search iterations)! 21 failed attempts to flush a page! Consider increasing the buffer pool size. It is also possible that in your Unix version fsync is very slow, or completely frozen inside the OS kernel. Then upgrading to a newer version of your operating system may help. Look at the number of fsyncs in diagnostic info below. Pending flushes (fsync) log: 0; buffer pool: 0. 167678974 OS file reads, 2271392 OS file writes, 758043 OS fsyncs. Starting InnoDB Monitor to print further diagnostics to the standard output.
最近唯一改變的是現在我們每周向客戶發送通知(僅限訂閱它的客戶),讓他們知道本週發生的某些事件。這是一個密集的過程,因為我們有幾千個客戶,但我們利用 Laravel 隊列來處理所有事情。
我嘗試
innodb_buffer_pool_size
從預設值更改為可用 RAM 的 80%(~13GB),而不是之前的消息,現在它顯示:
"InnoDB: page_cleaner: 1000ms intended loop took 4228ms. The settings might not be optimal."
.而這一變化使數據庫執行速度變慢。例如,處理 30k 條記錄(我提到的通知)需要 6 個小時,但在更改之前需要大約 3 個小時(當它沒有崩潰時)。
這是與 MySQL 設置相關的問題嗎?
編輯:innodb_* 建議更改後的全域狀態和變數
對於 4GB 的 droplet,將 config: 更改
innodb_buffer_pool_size
為 1500M 並重新啟動。對於 16GB 的 droplet,更改配置:
innodb_buffer_pool_size = 12G innodb_buffer_pool_instances = 12 innodb_page_cleaners = 12
修正分析 (執行一天多後)
觀察:
- 版本:5.7.24-0ubuntu0.18.04.1-log
- 16 GB 記憶體
- 正常執行時間 = 1d 02:59:16
- 您沒有在 Windows 上執行。
- 執行 64 位版本
- 您似乎完全(或大部分)執行 InnoDB。
更重要的問題:
很多表掃描,很多都很大。這可能會干擾其他 InnoDB 操作,從而間接停止 page_cleaners。
更改
innodb_lru_scan_depth = 256
為 page_cleaner 問題的可能解決方案。細節和其他觀察:
( innodb_lru_scan_depth ) = 1,024
– “InnoDB: page_cleaner: 1000ms 預期循環佔用了……”可以通過降低 lru_scan_depth 來修復
( Innodb_buffer_pool_pages_free / Innodb_buffer_pool_pages_total ) = 511,813 / 786384 = 65.1%
– buffer_pool 的 pct 目前未使用 – innodb_buffer_pool_size 比需要的大嗎?
( Innodb_buffer_pool_bytes_data / innodb_buffer_pool_size ) = 4,456,398,848 / 12288M = 34.6%
– 數據佔用緩衝池的百分比 – 小百分比可能表明 buffer_pool 過大。
( innodb_print_all_deadlocks ) = innodb_print_all_deadlocks = OFF
– 是否記錄所有死鎖。– 如果你被死鎖困擾,打開它。注意:如果你有很多死鎖,這可能會寫入很多磁碟。
( join_buffer_size / _ram ) = 262,144 / 16384M = 0.00%
– 每個執行緒 0-N。可以加快 JOIN(更好地修復查詢/索引)(所有引擎)用於索引掃描、範圍索引掃描、全表掃描、每個完整 JOIN 等。 – 如果很大,請減小 join_buffer_size 以避免記憶體壓力。建議少於 1% 的 RAM。如果很小,則將 RAM 增加到 0.01% 以改進一些查詢。
( local_infile ) = local_infile = ON
– local_infile = ON 是一個潛在的安全問題
( Handler_read_rnd_next / Com_select ) = 10,900,684,560 / 1418310 = 7,685
– 每個 SELECT 掃描的平均行數。(大約)——考慮提高 read_buffer_size(現在 128K;不清楚提高它是否有幫助)
( Select_scan ) = 233,714 / 97156 = 2.4 /sec
– 全表掃描 – 添加索引/優化查詢(除非它們是小表)
( Select_scan / Com_select ) = 233,714 / 1418310 = 16.5%
– % 的選擇進行全表掃描。(可能被儲存常式愚弄。)——添加索引/優化查詢
( Connections ) = 131,201 / 97156 = 1.4 /sec
– Connections – 增加wait_timeout;使用池化?異常小:
Innodb_dblwr_pages_written / Innodb_dblwr_writes = 2.31
異常大:
Com_show_plugins = 0.26 /HR Com_show_privileges = 0.037 /HR Com_stmt_close = 21 /sec Com_stmt_execute = 21 /sec Com_stmt_prepare = 21 /sec Innodb_buffer_pool_pages_free = 511,813 Performance_schema_file_instances_lost = 9 innodb_page_cleaners = 12 performance_schema_max_file_classes = 80 performance_schema_max_mutex_classes = 210
異常字元串:
innodb_fast_shutdown = 1 innodb_large_prefix = ON log_slow_admin_statements = ON
2018 年 12 月 23 日 每秒速率 = RPS – 為您的 my.cnf 考慮的建議
$$ mysqld $$部分,使用 2O18 年 11 月 22 日的 GLOBAL STATUS 和 GLOBAL VARIABLES 數據到 pastebin.com 數據
read_rnd_buffer_size=192K # from 256K to reduce handler_read_rnd_next RPS of 66,492 innodb_io_capacity=5000 # from 200 to enable higher IOPS on your SSD innodb_lru_scan_depth=100 # from 256 to reduce CPU busy every SECOND tmp_table_size=32M # from 16M to expand capacity max_heap_table_size=32M # from 16M to reduce created_tmp_disk_tables below 39%
觀察,我們通常看到的 Linux 作業系統
innodb_flush_method=O_DIRECT and you have 0 for the global variable.
如需其他建議,請查看我的個人資料、網路資料並與我聯繫。節日快樂。