
我有一個在 Ubuntu 12.04 伺服器上運行的 MySQL 實例,配備 120 GB RAM。有幾個 PHP 腳本在其上運行,有時會設定新的 mysql 參數。這些腳本之一使用大型 MEMORY 表來合併數據,然後再將資料插入 MySISAM 表。
最近,我將 max_heap_table_size 和 tmp_table_size 從 16 GB 更新為 20 GB,以避免「表已滿」錯誤。結果,MySQL 在下次執行腳本時崩潰了。
實際上它首先生成了一條軌跡:
14:30:19 UTC - mysqld got signal 11 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
We will try our best to scrape up some info that will hopefully help
diagnose the problem, but since we have already crashed,
something is definitely wrong and this may fail.
key_buffer_size=536870912
read_buffer_size=131072
max_used_connections=85
max_threads=700
thread_count=82
connection_count=81
It is possible that mysqld could use up to
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 2055554 K bytes of memory
Hope that's ok; if not, decrease some variables in the equation.
Thread pointer: 0x7ff66dbb4f30
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = 7ff632b80e60 thread_stack 0x28000
/usr/sbin/mysqld(my_print_stacktrace+0x29)[0x7ff66b087589]
/usr/sbin/mysqld(handle_fatal_signal+0x483)[0x7ff66af4c9d3]
/lib/x86_64-linux-gnu/libpthread.so.0(+0xfcb0)[0x7ff669c96cb0]
/usr/sbin/mysqld(_Z10field_convP5FieldS0_+0x37)[0x7ff66af49077]
/usr/sbin/mysqld(_ZN10Item_field13save_in_fieldEP5Fieldb+0x46)[0x7ff66af599b6]
/usr/sbin/mysqld(_Z11fill_recordP3THDPP5FieldR4ListI4ItemEb+0x4e)[0x7ff66adf3afe]
/usr/sbin/mysqld(_ZN12select_union9send_dataER4ListI4ItemE+0x6f)[0x7ff66aea705f]
/usr/sbin/mysqld(+0x32c554)[0x7ff66ae5a554]
/usr/sbin/mysqld(+0x3225cf)[0x7ff66ae505cf]
/usr/sbin/mysqld(_Z10sub_selectP4JOINP13st_join_tableb+0x7e)[0x7ff66ae5255e]
/usr/sbin/mysqld(+0x335274)[0x7ff66ae63274]
/usr/sbin/mysqld(_ZN4JOIN4execEv+0xc03)[0x7ff66ae72ec3]
/usr/sbin/mysqld(_Z12mysql_selectP3THDPPP4ItemP10TABLE_LISTjR4ListIS1_ES2_jP8st_orderSB_S2_SB_yP13select_resultP18st_select_lex_unitP13st_select_lex+0x130)[0x7ff66ae6e610]
/usr/sbin/mysqld(_Z21mysql_derived_fillingP3THDP3LEXP10TABLE_LIST+0x121)[0x7ff66ae13671]
/usr/sbin/mysqld(_Z20mysql_handle_derivedP3LEXPFbP3THDS0_P10TABLE_LISTE+0x68)[0x7ff66ae130f8]
/usr/sbin/mysqld(_Z20open_and_lock_tablesP3THDP10TABLE_LISTbjP19Prelocking_strategy+0x11a)[0x7ff66adf7c9a]
/usr/sbin/mysqld(+0x2fac95)[0x7ff66ae28c95]
/usr/sbin/mysqld(_Z21mysql_execute_commandP3THD+0x16a6)[0x7ff66ae307f6]
/usr/sbin/mysqld(_Z11mysql_parseP3THDPcjP12Parser_state+0x10f)[0x7ff66ae35a0f]
/usr/sbin/mysqld(_Z16dispatch_command19enum_server_commandP3THDPcj+0x1e71)[0x7ff66ae37951]
/usr/sbin/mysqld(_Z24do_handle_one_connectionP3THD+0x1bd)[0x7ff66aeddd9d]
/usr/sbin/mysqld(handle_one_connection+0x50)[0x7ff66aedde00]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x7e9a)[0x7ff669c8ee9a]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x6d)[0x7ff6693bf3fd]
Trying to get some variables.
Some pointers may be invalid and cause the dump to abort.
Query (7fea98004a80): is an invalid pointer
Connection ID (thread ID): 15144
Status: NOT_KILLED
The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains
information that should help you find out what is causing the crash.
一小時後發生崩潰/重啟:
131122 15:30:24 [Warning] Using unique option prefix myisam-recover instead of myisam-recover-options is deprecated and will be removed in a future release. Please use the full name instead.
131122 15:30:24 [Warning] Using unique option prefix myisam-recover instead of myisam-recover-options is deprecated and will be removed in a future release. Please use the full name instead.
131122 15:30:24 [Note] Plugin 'FEDERATED' is disabled.
131122 15:30:24 InnoDB: The InnoDB memory heap is disabled
131122 15:30:24 InnoDB: Mutexes and rw_locks use GCC atomic builtins
131122 15:30:24 InnoDB: Compressed tables use zlib 1.2.3.4
131122 15:30:24 InnoDB: Initializing buffer pool, size = 128.0M
131122 15:30:24 InnoDB: Completed initialization of buffer pool
131122 15:30:24 InnoDB: highest supported file format is Barracuda.
InnoDB: Log scan progressed past the checkpoint lsn 1319218667
131122 15:30:24 InnoDB: Database was not shut down normally!
InnoDB: Starting crash recovery.
不幸的是,我沒有可以在此處發布的二進位日誌或慢查詢日誌輸出,但我可以說的是,PHP 腳本在生成堆疊追蹤後繼續運行。它在 mysql 重新啟動期間停止。
不應考慮硬體故障,因為此錯誤已發生在 2 個不同的伺服器上。
墜機的原因可能是什麼?如何找出可以使用的最大 max_heap_table_size 和 tmp_table_size 而不會導致 mysql 崩潰?
ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 1031141
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 1031141
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
Ubuntu 12.04,1 的 mysql 版本是 5.5.34
答案1
有了 120GB 內存,您的機器似乎還可能擁有多個物理 CPU 和非統一內存訪問 (NUMA) 架構……如果是這樣的話,您可能擁有大量可用內存,但仍然與直覺相反,可用內存不足。
如果到目前為止我進展順利,那麼當 MySQL 嘗試增加分配給表的內存時,您可能會遇到這個問題MEMORY
,並且遇到與Linux 在此體系結構上運行時處理內存分配的方式相關的錯誤- 僅透過考慮到直接連接到某個特定CPU 的內存棒上的可用內存,該CPU 在某種程度上被任意選擇為將服務內存請求的“那個”——儘管主板上其他地方的其他物理內存是空閒的。
NUMA 理論上很好,但可能不太適合需要大量記憶體的單一進程,就像 MySQL 的情況一樣……但是有一個解決方法。
修復方法是mysqld_safe
透過新增以下行來修改腳本:
cmd="/usr/bin/numactl --interleave all $cmd"
……立即地後這條線...
cmd="$NOHUP_NICENESS"
這裡解釋了原因,在一篇優秀的文章中,這篇文章最初是為了解決為什麼具有這種架構的 MySQL 伺服器儘管有可用記憶體而大量交換的;然而,這是作者所面臨的一個更大問題的徵兆。隨後指出“不完全是交換問題”,即使禁用交換,也可能包括“記憶體分配失敗”。
http://blog.jcole.us/2010/09/28/mysql-swap-insanity-and-the-numa-architecture/
當然,我正在猜測這是否適用於您的系統,但這似乎是值得的可能性。當我嘗試配置 64GB InnoDB 緩衝池並且 MySQL 無法在機器上找到 64GB 可用空間時,我在新的 128GB 機器上遇到問題時,我正是使用了此修復程序沒有什麼否則運行。當我意識到我可以成功使用的最高值小於 16 核心機器(具有 4 個處理器)的總記憶體的 1/4 時,身體的處理器......有點像你似乎遇到的......是當我將各個部分放在一起以了解問題的本質時。
答案2
的文檔tmp_表大小表示此設定是臨時表可以達到的最大大小在記憶中。超過該大小不會觸發任何表已滿錯誤;它觸發從使用記憶體中的表到使用磁碟上的 MyISAM 表的變更。
系統正在崩潰,因為您允許臨時表使用比應有的更多的記憶體。與內存表相同。
您應該刪除 tmp_table_size方式向下。請記住,此設定不是總體最大值。這是每個臨時表的最大值。如果您有 5 個查詢產生一個巨大的臨時表(例如每個查詢不到 20GB),那麼您現在的臨時表會佔用 100GB 的 RAM。再加上第六個,您使用的 RAM 就比伺服器的總記憶體還要多。
如果您的腳本實際上使用 MEMORY 儲存引擎,那麼在您應該考慮更改之後將資料寫入 MyISAM 檔案。如果確實需要在這麼大的臨時表上實現如此快速的效能,那麼您應該考慮獲得更快的儲存(例如,融合io,維登特等)。如果這些太過分或太貴,我至少會考慮消費級 SSD。
當 MyISAM 的資料快取到系統記憶體(未使用的 RAM)時,其效能最佳。如果您的腳本每次進行大型查詢(使用 MEMORY 引擎)時都會耗盡緩存,那麼您的 MyISAM 效能將會受到影響。
我懷疑該腳本在實際殺死它時正在使用 MEMORY 儲存引擎來「提高」效能。如果它是臨時表,則應該使用臨時表,並且您的 tmp_table_size 應該小得多,在破壞 tmp_table_size 後強制將其儲存到磁碟。
max_heap_table_size 和 tmp_table_size 的預設值都是 16MB。如果可能的話,我建議將設定更改回預設值。以小增量向上調整,同時監控資源使用情況(磁碟 I/O、總記憶體使用情況、CPU 使用情況等),直到找到適合您的資料集的設定。