Percona XtraDB Cluster (5.6.28-76.1-56-log) - 隨機 OOM 事件
我們有一個多節點(每個 64G RAM)集群。主節點(我們用於變異數據的節點)隨機只是 OOM,這在高峰時間和極其安靜的時間都會發生。
我們在 OOM 事件之前註意到的通常是一堆等待主節點上鎖的事務。MySQL Tuner 建議 mysql 的最大可能使用量是 59G,但是當它開始累積時,它會耗盡盒子上的所有資源並發生 OOM 事件。那個盒子上沒有其他東西在執行。
該事件的最後一次發生是在一個安靜的時期,那裡的連接數量非常少(少於 150 個),甚至更不積極地做任何事情。
我能得到任何關於可能導致 MySQL 超過記憶體方面的最大值的指針嗎?
我們的 my.cnf(稍微清理一下)
[mysqld] datadir = /var/lib/mysql long_query_time = 5 slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow_query.log log_bin = mysql-bin log_error = /var/log/mysql/error.log tmpdir = /var/lib/mysql/.tmpdir binlog_format = ROW default_storage_engine = InnoDB expire_logs_days = 28 ft_min_word_len = 1 ft_stopword_file = '' join_buffer_size = 16M key_buffer_size = 24M lc-messages-dir = /usr/share/mysql lower_case_table_names = 0 max_allowed_packet = 512M max_connections = 400 max_heap_table_size = 6G memlock = 0 myisam-recover = BACKUP query_cache_limit = 4M query_cache_size = 64M query_cache_type = 1 read_buffer_size = 2M read_rnd_buffer_size = 16M skip-external-locking skip_name_resolve sort_buffer_size = 10M sysdate_is_now = 1 table_open_cache = 1024 thread_cache_size = 512 thread_stack = 192K tmp_table_size = 6G explicit_defaults_for_timestamp = 1 innodb_autoinc_lock_mode = 2 innodb_buffer_pool_instances = 8 innodb_buffer_pool_size = 32G innodb_doublewrite = 1 innodb_file_per_table = 1 innodb_flush_log_at_trx_commit = 2 innodb_flush_method = O_DIRECT innodb_io_capacity = 200 innodb_log_buffer_size = 96M innodb_log_files_in_group = 2 innodb_log_file_size = 1024M innodb_read_io_threads = 4 innodb_thread_concurrency = 0 innodb_locks_unsafe_for_binlog = 1 innodb_write_io_threads = 4 innodb_ft_min_token_size = 0 innodb_stats_on_metadata = 0
按要求提供的附加資訊:
執行緒數 = 每個節點 16
使用預置的 1024 iops (aws),每個節點具有 1024G 儲存
顯示全域狀態:https ://pastebin.com/kpiWrERR
顯示全域變數:https ://pastebin.com/x3uXrvJs
mysqltuner 輸出:https ://pastebin.com/7uGHQsGy (我們已經經歷了幾次迭代)
還有其他各種系統程序在那個盒子上執行,但它們都沒有使用超過正常值,並且它們的記憶體使用量也被考慮在內,恐怕這就是我可以分享的全部內容。
我發現了幾個嚴重的問題:
觀察:
- 版本:5.6.28-76.1-56-log
- 64 GB 記憶體
- 正常執行時間 = 1 天 16:08:17
- 您沒有在 Windows 上執行。
- 執行 64 位版本
- 您似乎完全(或大部分)執行 InnoDB。
更重要的問題:
max_heap_table_size 和 tmp_table_size 為 6G。對於您的 64G 機器,不要將它們設置為 600M(RAM 的 1%)以上。可能發生的情況是多個大型查詢正在建構臨時表(下面有更多證據)並佔用大量 RAM。將臨時表溢出到磁碟比導致交換或 OOM 更好。此外,查看慢日誌將有助於辨識這些頑皮的查詢。
查詢記憶體可能應該被關閉。它正在做很多李子。QC 在生產系統中很少實用,因為每個 INSERT 都會導致 QC 中相關表的所有項目被清除。這代價不菲。一種折衷方案是選擇性地使用它(參見 DEMAND)並在 SELECT 上使用 SQL_CACHE 或 SQL_NO_CACHE。
假設你有 SSD,你應該增加 innodb_io_capacity(到 1000),也許還有一些類似的設置。
32G buffer_pool,但是 Innodb_buffer_pool_reads = 344/second – 聽起來很多查詢都在做表掃描。還有 119 個臨時表/秒;34 在磁碟上。使用慢日誌來追踪它們。
為什麼會有這麼多 ROLLBACK?
為什麼如此頻繁地顯示引擎狀態?(每秒一次!)
你在監控死鎖嗎?建議
innodb_print_all_deadlocks = ON
其他一些 SHOW 命令非常頻繁。請記住,它們會影響性能。也許不那麼頻繁地執行它們。
我很少發現 REPLACE 是實用的;檢查您的使用情況。
如果您使用的是 FULLTEXT 索引,我懷疑這
innodb_ft_min_token_size = 0
是“錯誤的”。如果您使用的是分區表,請提供 SHOW CREATE TABLE 進行評論。
6節點集群?– 節點相距多遠?網路是否飽和?(每個節點在每次寫入時都與其他 5 個節點進行通信。)
考慮打開 wsrep_log_conflicts 。
細節和其他觀察:
( Key_reads + Key_writes + Innodb_pages_read + Innodb_pages_written + Innodb_dblwr_writes + Innodb_buffer_pool_pages_flushed ) = (340 + 0 + 53517294 + 5637805 + 714833 + 5637805) / 144497 = 453 /sec
——眼壓?– 如果硬體可以處理,將 innodb_io_capacity(現在為 200)設置為這個值。
( ( Key_reads + Key_writes + Innodb_pages_read + Innodb_pages_written + Innodb_dblwr_writes + Innodb_buffer_pool_pages_flushed ) / innodb_io_capacity / Uptime ) = ( 340 + 0 + 53517294 + 5637805 + 714833 + 5637805 ) / 200 / 144497 = 226.7%
– 這可能是一個指標,表明合理設置了 innodb_io_capacity。– 如果硬體可以處理,則增加 innodb_io_capacity(現在為 200)。
( innodb_buffer_pool_size / innodb_buffer_pool_instances ) = 32768M / 8 = 4096MB
– 每個 buffer_pool 實例的大小。– 一個實例至少應為 1GB。在非常大的 RAM 中,有 16 個實例。
( innodb_lru_scan_depth ) = 1,024
– “InnoDB: page_cleaner: 1000ms 預期循環佔用了……”可以通過降低 lru_scan_depth 來修復
( innodb_io_capacity_max / innodb_io_capacity ) = 2,000 / 200 = 10
– 容量:max/plain – 推薦 2. Max 應該大約等於您的 I/O 子系統可以處理的 IOP。(如果驅動器類型未知,2000/200 可能是合理的一對。)
( Innodb_buffer_pool_reads ) = 49,797,223 / 144497 = 344 /sec
– 在 buffer_pool 中記憶體未命中。– 增加innodb_buffer_pool_size(現在是34359738368)?(~100 是 HDD 的限制,~1000 是 SSD 的限制。)
( (Innodb_buffer_pool_reads + Innodb_buffer_pool_pages_flushed) ) = ((49797223 + 5637805) ) / 144497 = 383 /sec
– InnoDB I/O – 增加 innodb_buffer_pool_size(現在是 34359738368)?
( Innodb_log_writes ) = 7,403,188 / 144497 = 51 /sec
( Com_rollback ) = 2,211,653 / 144497 = 15 /sec
– InnoDB 中的回滾。– 回滾頻率過高可能表明應用程序邏輯效率低下。
( Handler_rollback ) = 4,550,132 / 144497 = 31 /sec
——為什麼有這麼多回滾?
( Innodb_row_lock_waits ) = 20,978 / 144497 = 0.15 /sec
– 獲取行鎖延遲的頻率。– 可能是由可以優化的複雜查詢引起的。
( Innodb_deadlocks ) = 1 / 144497 = 0.025 /HR
– 死鎖 – SHOW ENGINE INNODB STATUS;查看最新的一對死鎖的查詢。
( innodb_flush_neighbors ) = 1
– 將塊寫入磁碟時的小優化。– 使用 0 表示 SSD 驅動器;1 用於硬碟。
( ( Innodb_pages_read + Innodb_pages_written ) / Uptime / innodb_io_capacity ) = ( 53517294 + 5637805 ) / 144497 / 200 = 204.7%
– 如果 > 100%,需要更多的 io_capacity。– 如果驅動器可以處理,則增加 innodb_io_capacity(現在為 200)。
( innodb_io_capacity ) = 200
- 磁碟上每秒的 I/O 操作數。100 用於慢速驅動器;200 用於旋轉驅動器;SSD 1000-2000;乘以 RAID 係數。
( expand_fast_index_creation ) = expand_fast_index_creation = OFF
– 使用 ON 可以大大加快 ALTER 和 OPTIMIZE。- 可能更好的是。
( sync_binlog ) = 0
– 使用 1 來增加安全性,以 I/O 為代價 =1 可能會導致大量“查詢結束”;=0 可能會導致“binlog 在不可能的位置”並在崩潰中失去事務,但速度更快。
( innodb_print_all_deadlocks ) = innodb_print_all_deadlocks = OFF
– 是否記錄所有死鎖。– 如果你被死鎖困擾,打開它。注意:如果你有很多死鎖,這可能會寫入很多磁碟。
( min( tmp_table_size, max_heap_table_size ) ) = (min( 6144M, 6144M )) / 65536M = 9.4%
– 當需要 MEMORY 表(每個表)或 SELECT 內的臨時表(每個 SELECT 的每個臨時表)時分配的 RAM 百分比。太高可能會導致交換。– 將 tmp_table_size(現在為 6442450944)和 max_heap_table_size(現在為 6442450944)減少到 1% 的記憶體。
( innodb_buffer_pool_populate ) = OFF = 0
– NUMA 控制
( character_set_server ) = character_set_server = latin1
– 將 character_set_server(現在是 latin1)設置為 utf8mb4 可以幫助解決字元集問題。那是未來的預設值。
( local_infile ) = local_infile = ON
– local_infile (now ON) = ON 是一個潛在的安全問題
( Qcache_lowmem_prunes ) = 80,501,088 / 144497 = 557 /sec
– QC 空間不足 – 增加 query_cache_size(現在為 67108864)
( Qcache_lowmem_prunes/Qcache_inserts ) = 80,501,088/141879824 = 56.7%
– Removal Ratio(由於記憶體不足而需要修剪的頻率)
( Qcache_not_cached ) = 40,419,444 / 144497 = 279 /sec
– SQL_CACHE 已嘗試,但被忽略 – 重新考慮記憶體;調整 qcache
( Qcache_inserts - Qcache_queries_in_cache ) = (141879824 - 16616) / 144497 = 981 /sec
- 失效/秒。
( (query_cache_size - Qcache_free_memory) / Qcache_queries_in_cache / query_alloc_block_size ) = (64M - 24496808) / 16616 / 8192 = 0.313
– query_alloc_block_size vs formula – 調整 query_alloc_block_size (現在 8192)
( Questions ) = 632,680,020 / 144497 = 4378 /sec
– 查詢(SP 外) – “qps” – >2000可能對伺服器造成壓力
( Queries ) = 634,675,672 / 144497 = 4392 /sec
– 查詢(包括 SP 內部) – >3000可能對伺服器造成壓力
( Created_tmp_tables ) = 17,211,890 / 144497 = 119 /sec
– 創建“臨時”表作為複雜 SELECT 的一部分的頻率。
( Created_tmp_disk_tables ) = 4,880,505 / 144497 = 34 /sec
– 作為複雜 SELECT 的一部分創建磁碟“臨時”表的頻率 – 增加 tmp_table_size(現在為 6442450944)和 max_heap_table_size(現在為 6442450944)。檢查何時使用 MEMORY 而不是 MyISAM 的臨時表規則。也許較小的模式或查詢更改可以避免 MyISAM。更好的索引和查詢的重新制定更有可能有所幫助。
( tmp_table_size ) = 6144M
– 限制用於支持 SELECT 的MEMORY臨時表的大小 – 減少 tmp_table_size(現在為 6442450944)以避免記憶體不足。也許不超過64M。
( Com_rollback / (Com_commit + Com_rollback) ) = 2,211,653 / (5878741 + 2211653) = 27.3%
– Rollback : Commit ratio – 回滾成本很高;更改應用邏輯
( Select_full_join ) = 1,238,385 / 144497 = 8.6 /sec
– 無索引連接 – 為 JOIN 中使用的表添加合適的索引。
( Select_range_check ) = 369,822 / 144497 = 2.6 /sec
– 沒有好的索引 – 查找慢查詢;檢查索引。
( Select_scan ) = 10,971,747 / 144497 = 76 /sec
– 全表掃描 – 添加索引/優化查詢(除非它們是小表)
( Select_scan / Com_select ) = 10,971,747 / 182457623 = 6.0%
– % 的選擇進行全表掃描。(可能被儲存常式愚弄。)——添加索引/優化查詢
( sort_buffer_size ) = 10M
– 每個執行緒一個,在 5.6.4 之前以全尺寸分配,所以保持低;在那之後更大就可以了。– 這可能會佔用可用的 RAM;建議不要超過2M。
( Com_insert + Com_delete + Com_delete_multi + Com_replace + Com_update + Com_update_multi ) = (15287078 + 413037 + 137592 + 2417207 + 40196282 + 118467) / 144497 = 405 /sec
– writes/sec – 50 writes/sec + 日誌刷新可能會最大化普通驅動器的 I/O 寫入容量
( Com_replace ) = 2,417,207 / 144497 = 17 /sec
– 考慮更改為 INSERT … ON DUPLICATE KEY UPDATE。
( binlog_error_action ) = binlog_error_action = IGNORE_ERROR
– 無法寫入binlog怎麼辦。– IGNORE_ERROR 是向後兼容的預設值,但建議使用 ABORT_SERVER。
( long_query_time ) = 5
– 用於定義“慢”查詢的截止時間(秒)。– 建議 2
( log_slow_slave_statements ) = log_slow_slave_statements = OFF
– (5.6.11, 5.7.1) 預設情況下,複製的語句不會出現在慢日誌中;這導致他們顯示。– 在慢日誌中查看可能干擾從屬讀取的寫入會很有幫助。
( Connections ) = 4,437,295 / 144497 = 31 /sec
– Connections – 增加wait_timeout(現在是28800);使用池化?
( thread_cache_size / Max_used_connections ) = 512 / 197 = 259.9%
- 讓執行緒記憶體大於您可能的連接數沒有任何優勢。浪費空間是缺點。
異常小:
Innodb_master_thread_idle_loops = 5 innodb_ft_min_token_size = 0
異常大:
Bytes_received = 1623600 /sec Bytes_sent = 7156640 /sec Com_begin = 57 /sec Com_delete_multi = 0.95 /sec Com_kill = 0.35 /HR Com_rename_table = 3.9 /HR Com_show_binlogs = 12 /HR Com_show_engine_status = 0.99 /sec Com_show_keys = 0.073 /sec Com_show_processlist = 0.99 /sec Com_show_slave_hosts = 0.075 /HR Com_show_slave_status_nolock = 24 /HR Com_show_status = 1.2 /sec Com_show_storage_engines = 12 /HR Com_update = 278 /sec Com_update_multi = 0.82 /sec Handler_commit = 3457 /sec Handler_external_lock = 4188 /sec Handler_prepare = 379 /sec Handler_read_key = 124114 /sec Handler_read_last = 2.2 /sec Handler_read_next = 2416004 /sec Handler_read_prev = 37046 /sec Handler_read_rnd = 66035 /sec Handler_update = 1951 /sec Innodb_buffer_pool_pages_dirty = 95,455 Innodb_buffer_pool_pages_made_not_young = 11177 /sec Innodb_buffer_pool_pages_made_young = 323 /sec Innodb_buffer_pool_pages_misc = 149,890 Innodb_buffer_pool_read_requests = 2506430 /sec Innodb_data_read = 6068079 /sec Innodb_data_reads = 370 /sec Innodb_ibuf_free_list = 156,712 Innodb_ibuf_merged_deletes = 1.6 /sec Innodb_ibuf_merged_inserts = 15 /sec Innodb_ibuf_merges = 11 /sec Innodb_ibuf_segment_size = 156,845 Innodb_ibuf_size = 132 Innodb_rows_read = 3497480 /sec Innodb_s_lock_spin_rounds = 3604 /sec Innodb_s_lock_spin_waits = 1130 /sec Key_write_requests = 331 /sec Qcache_hits = 2538 /sec Qcache_inserts = 981 /sec Select_full_range_join = 17 /sec Select_full_range_join / Com_select = 1.3% Select_range = 100 /sec Sort_range = 151 /sec Sort_rows = 15547 /sec Sort_scan = 65 /sec Table_locks_immediate = 2076 /sec Threads_cached = 127 auto_increment_offset = 5 max_heap_table_size = 6144MB min(max_heap_table_size, tmp_table_size) = 6144MB wsrep_cluster_size = 6 wsrep_slave_threads = 8
異常字元串:
Compression = ON ft_min_word_len = 1 ft_stopword_file = innodb_fast_shutdown = 1 innodb_locks_unsafe_for_binlog = ON optimizer_trace = enabled=off,one_line=off optimizer_trace_features = greedy_search=on, range_optimizer=on, dynamic_range=on, repeated_subselect=on slave_rows_search_algorithms = TABLE_SCAN,INDEX_SCAN wsrep_cluster_status = Primary wsrep_connected = ON wsrep_provider = /usr/lib64/galera3/libgalera_smm.so wsrep_provider_name = Galera wsrep_provider_vendor = Codership Oy wsrep_provider_version = 3.14(r53b88eb) wsrep_sst_method = xtrabackup-v2
慢日誌
http://mysql.rjweb.org/doc.php/mysql_analysis#slow_queries_and_slowlog