淺談MySQL數(shù)據(jù)庫(kù)崩潰(crash)的常見(jiàn)原因和解決辦法
檢查 MySQL 數(shù)據(jù)庫(kù)的啟動(dòng)時(shí)間
Linux 系統(tǒng)中的 systemd 和 mysqld_safe 會(huì)在 mysqld 進(jìn)程 crash 后自動(dòng)重新啟動(dòng) MySQL 的服務(wù),需要注意的是使用 kill -9 殺死 mysqld 進(jìn)程系統(tǒng)會(huì)自動(dòng)重新啟動(dòng),而只使用 kill 命令則不會(huì)重新啟動(dòng),因?yàn)閳?zhí)行 kill 命令,系統(tǒng)會(huì)發(fā)送一個(gè) SIGTERM 信號(hào)給 mysqld,mysql 數(shù)據(jù)庫(kù)會(huì)正常關(guān)閉,日志中會(huì)出現(xiàn)類(lèi)似下面的記錄:
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 數(shù)據(jù)庫(kù) crash 后都會(huì)重新啟動(dòng),因此我們有時(shí)可能不知道 MySQL 數(shù)據(jù)庫(kù)已經(jīng) crash 過(guò)了,但我們可以從mysql數(shù)據(jù)庫(kù)啟動(dòng)時(shí)間上找到線(xiàn)索,下面介紹四種檢查 MySQL 數(shù)據(jù)庫(kù)啟動(dòng)時(shí)間的方法。
檢查 MySQL 服務(wù)狀態(tài)
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 數(shù)據(jù)庫(kù)已經(jīng)運(yùn)行 4 天多。
檢查 MySQL 中的 uptime 狀態(tài)
mysql> show global status like 'uptime'; +---------------+--------+ | Variable_name | Value | +---------------+--------+ | Uptime | 428334 | +---------------+--------+ 1 row in set (0.32 sec)
這個(gè)值是以秒為單位,下面換算成以天為單位是 4 天多。
mysql> select 428334/60/60/24; +-----------------+ | 428334/60/60/24 | +-----------------+ | 4.957569444444 | +-----------------+ 1 row in set (0.01 sec)
查詢(xún) uptime 狀態(tài)的另一種方法是使用 mysqladmin version 或在 mysql 客戶(hù)端里用 “\s” 進(jìn)行查詢(xún)。
使用 ps 檢查進(jìn)程啟動(dòng)時(shí)間
使用 ps 命令查詢(xún)發(fā)現(xiàn) mysqld 啟動(dòng)了4天23小時(shí)3分種54秒
scutech@scutech:~$ ps -eo pid,user,args,etime|grep mysqld 791 mysql /usr/sbin/mysqld --daemoniz 4-23:03:54
檢查 MySQL 日志
找關(guān)鍵字 “ready for connections”,可以查到啟動(dòng)信息。
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 數(shù)據(jù)庫(kù) crash 的常見(jiàn)原因
MySQL 數(shù)據(jù)庫(kù) crash 的最常見(jiàn)原因有兩個(gè),一個(gè)是 mysql 的 bug , 另一個(gè)是 mysql 申請(qǐng)系統(tǒng)資源失敗或內(nèi)存泄漏。
MySQL 的 bug
MySQL數(shù)據(jù)庫(kù) crash 的最常見(jiàn)的一個(gè)原因當(dāng)然是 MySQL 的bug。95% 的 bug 都是和具體的 sql 相關(guān),通常是 MySQL crash 前執(zhí)行的最后一個(gè) sql 有問(wèn)題,因此定位 bug 時(shí)應(yīng)打開(kāi) general query log ,根據(jù)最后一個(gè) sql 來(lái)查找線(xiàn)索。
當(dāng)你確定了 crash 的原因后,應(yīng)該檢查一下 MySQL 的 bug 庫(kù)(https://bugs.mysql.com),通常采用 Advanced search,看看有沒(méi)有類(lèi)似的問(wèn)題。如果你找到了可能與你相關(guān)的 bug,確認(rèn)它是否修復(fù)了。如果已經(jīng)修復(fù)了,那么把 MySQL 升級(jí)到 bug 已經(jīng)修復(fù)的版本。
在每個(gè)版本的 Release Notes 里面有一節(jié) Bugs Fixed ,可以查到修復(fù)的 bug 。
MySQL 申請(qǐng)系統(tǒng)資源失敗或內(nèi)存泄漏
內(nèi)存不足或 MySQL 申請(qǐng)系統(tǒng)資源失敗外都會(huì)造成 MySQL 崩潰,例如磁盤(pán)空間滿(mǎn)了,磁盤(pán)上的文件 corrupt 等。此時(shí)需要定位 crash 的根本原因有下面幾種方法:
- 仔細(xì)閱讀 MySQL 的錯(cuò)誤日志,這個(gè)日志里面的一些程序調(diào)試信息看起來(lái)很讓人困惑,但靜下心來(lái)仔細(xì)看,很多時(shí)候會(huì)找到線(xiàn)索;
- 打開(kāi) general query log ,找到最后一個(gè) sql 訪(fǎng)問(wèn)的表或索引,檢查這個(gè)表或索引,如果有問(wèn)題就重建,通??梢越鉀Q問(wèn)題。
- 使用 strace、pstack、pmap、gdb 分析 mysqld 的代碼,可能需要打開(kāi) core dump;
- 使用 CMake 的選項(xiàng) -DWITH_DEBUG=1 重新編譯 mysqld,然后運(yùn)行重新編譯后的 mysqld,查看 trace 文件、error log 進(jìn)行排錯(cuò)。
MySQL 內(nèi)存占用的計(jì)算
全局內(nèi)存
innodb_buffer_pool_size innodb_log_buffer_size thread_cache_size table_open_cache table_definition_cache key_buffer_size
線(xiàn)程內(nèi)存
binlog_cache_size thread_stack
單次操作內(nèi)存
join_buffer_size read_buffer_size read_rnd_buffer_size tmp_table_size sort_buffer_size
計(jì)算公式
MySQL 8 中最大內(nèi)存占用參考值計(jì)算公式:
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;
innodb_buffer_pool_size
- key_buffer_size
- max_connections*(sort_buffer_size+read_buffer_size+binlog_cache_size)
- max_connections*2MB
臨時(shí)解決可以使用下面的命令釋放緩存:
echo 1 > /proc/sys/vm/drop_caches
0:0是系統(tǒng)默認(rèn)值,默認(rèn)情況下表示不釋放內(nèi)存,由操作系統(tǒng)自動(dòng)管理
1:釋放頁(yè)緩存
2:釋放dentries和inodes
3:釋放所有緩存
從長(zhǎng)遠(yuǎn)看還是要修改對(duì)應(yīng)的參數(shù)進(jìn)行解決。
MySQL 客戶(hù)端的內(nèi)存泄漏
MySQL 客戶(hù)端的內(nèi)存泄漏時(shí)通常會(huì)有下面的提示
mysql: Out of memory at line 42, 'malloc.c'
mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k)
ERROR 2008: MySQL client ran out of memory
這通常是客戶(hù)端收到的返回結(jié)果集太大造成的,解決辦法有兩種:
檢查正在運(yùn)行的 SQL ,看看您真的需要這么大的返回結(jié)果集嗎?
允許 mysql 時(shí)加上 --quick 選項(xiàng),這會(huì)減少客戶(hù)端單次收到的返回集,但會(huì)增加 mysqld 的負(fù)載。
到此這篇關(guān)于淺談MySQL數(shù)據(jù)庫(kù)崩潰(crash)的常見(jiàn)原因和解決辦法的文章就介紹到這了,更多相關(guān)MySQL數(shù)據(jù)庫(kù)崩潰內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
centos編譯安裝mysql 5.6及安裝多個(gè)mysql實(shí)例詳解
這篇文章主要介紹了centos編譯安裝mysql 5.6及安裝多個(gè)mysql實(shí)例詳解,需要的朋友可以參考下2017-02-02SQL刪除重復(fù)數(shù)據(jù)的實(shí)例教程
在使用SQL提數(shù)的時(shí)候,常會(huì)遇到表內(nèi)有重復(fù)值的時(shí)候,下面這篇文章主要給大家介紹了關(guān)于SQL刪除重復(fù)數(shù)據(jù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07

MySQL數(shù)據(jù)庫(kù)中null的知識(shí)點(diǎn)總結(jié)

MySQL數(shù)據(jù)庫(kù)升級(jí)的一些"陷阱"

MySQL中l(wèi)imit對(duì)查詢(xún)語(yǔ)句性能的影響