Linux 系統中的systemd 和mysqld_safe 會在mysqld 程序crash 後自動重新啟動MySQL 的服務,需要注意的是使用kill -9 殺死mysqld 程序系統會自動重新啟動,而只使用kill 指令則不會重新啟動,因為執行kill 指令,系統會傳送一個SIGTERM 訊號給mysqld,mysql 資料庫會正常關閉,日誌會出現類似下面的記錄:
2020-10-26T09:06:48.435181Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.19 ) MySQL Community Server - GPL.
MySQL 資料庫crash 之後都會重新啟動,因此我們有時可能不知道MySQL 資料庫已經crash 過了,但我們可以從mysql資料庫啟動時間上找到線索,下面介紹四種檢查MySQL 資料庫啟動時間的方法。
scutech@scutech:~$ service mysql status ● mysql.service - MySQL Community Server Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2020-10-21 05:54:18 NDT; 4 days ago Process: 774 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid (code=exited, status=0/SUCCESS) Process: 708 ExecStartPre=/usr/share/mysql/mysql-systemd-start pre (code=exited, status=0/SUCCESS) Main PID: 791 (mysqld) Tasks: 27 (limit: 2328) CGroup: /system.slice/mysql.service └─791 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid
顯示 MySQL 資料庫已經運行 4 天多。
mysql> show global status like 'uptime'; +---------------+--------+ | Variable_name | Value | +---------------+--------+ | Uptime | 428334 | +---------------+--------+ 1 row in set (0.32 sec)
這個值是以秒為單位,下面換算成以天為單位是 4 天多。
mysql> select 428334/60/60/24; +-----------------+ | 428334/60/60/24 | +-----------------+ | 4.957569444444 | +-----------------+ 1 row in set (0.01 sec)
查詢 uptime 狀態的另一種方法是使用 mysqladmin version 或在 mysql 用戶端裡用 “\s” 進行查詢。
使用ps 指令查詢發現mysqld 啟動了4天23小時3分種54秒
scutech@scutech:~$ ps -eo pid,user,args,etime|grep mysqld 791 mysql /usr/sbin/mysqld --daemoniz 4-23:03:54
找關鍵字“ready for connections”,可以查到啟動訊息。
2020-10-21T08:24:18.986765Z 0 [Note] /usr/sbin/mysqld: ready for connections.
Version: '5.7.28-log' socket: '/ var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
MySQL 資料庫crash 的最常見原因有兩個,一個是mysql 的bug , 另一個是mysql 申請系統資源失敗或記憶體洩漏。
MySQL資料庫 crash 的最常見的一個原因當然是 MySQL 的bug。 95% 的 bug 都是和特定的 sql 相關,通常是 MySQL crash 前執行的最後一個 sql 有問題,因此定位 bug 時應打開 general query log ,根據最後一個 sql 來查找線索。
當你確定了 crash 的原因後,應該檢查一下 MySQL 的 bug 函式庫(https://bugs.mysql.com),通常採用 Advanced search,看看有沒有類似的問題。如果你找到了可能與你相關的 bug,確認它是否修復了。如果已經修復了,那麼把 MySQL 升級到 bug 已經修復的版本。
在每個版本的 Release Notes 裡面有一節 Bugs Fixed ,可以查到修復的 bug 。
記憶體不足或 MySQL 申請系統資源失敗外都會造成 MySQL 崩潰,例如磁碟空間滿了,磁碟上的檔案 corrupt 等。此時需要定位crash 的根本原因有以下幾種方法:
仔細閱讀MySQL 的錯誤日誌,這個日誌裡面的一些程式偵錯資訊看起來很困惑,但靜下心來仔細看,很多時候會找到線索;
#打開general query log ,找到最後一個sql 訪問的表或索引,檢查這個表或索引,如果有問題就重建,通常可以解決問題。
使用strace、pstack、pmap、gdb 分析mysqld 的程式碼,可能需要開啟core dump;
使用CMake 的選項-DWITH_DEBUG= 1 重新編譯mysqld,然後執行重新編譯後的mysqld,查看trace 檔案、error log 進行排錯。
全域記憶體
innodb_buffer_pool_size innodb_log_buffer_size thread_cache_size table_open_cache table_pool_size_cache_log_buffer_size thread_cache_size table_open_cache table_definition_cache key_buffer_sizeth#c_ache_achesize#c_ic_ache_size#c_ache_ache_sizeth#c_ache_記憶體
join_buffer_size read_buffer_size read_rnd_buffer_size tmp_table_size sort_buffer_size
計算公式
MySQL 8 中最大記憶體佔用參考值計算公式:#odr
max_connections*(sort_buffer_size read_buffer_size binlog_cache_size)
max_connections*2MB
SELECT ( @@innodb_buffer_pool_size + @@innodb_log_buffer_size + @@key_buffer_size + @@max_connections * (@@binlog_cache_size + @@thread_stack + @@read_buffer_size + @@read_rnd_buffer_size + @@sort_buffer_size + @@join_buffer_size + @@tmp_table_size ) ) / 1024 /1024 AS MAX_MEM_MB;
1:釋放頁快取
2:釋放dentries和inodes
MySQL 用戶端的記憶體洩漏時通常會有下面的提示
這通常是客戶端收到的回傳結果集太大造成的,解決方案有兩種:mysql: Out of memory at line 42, 'malloc.c'
ERROR 2008: My SQLclientran out of memory
mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k)
ERROR 12481367 bytes (12189k)
檢查正在執行的SQL ,看看您真的需要這麼大的回傳結果集嗎?
以上是MySQL資料庫崩潰的常見原因和解決方法是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!