TLDR#
- 問題:log 檔案過大,將剩餘空間占滿,導致服務異常
- 原因:MySQL 被設定開啟 mysql-gen.log,且未設定定時清理
- 調查方法:檢查 MySQL 設定與空間占用狀況
- 解決方案:使用 logrotate 設定定時清理
正式環境的 MySQL Slave 會定期製作分析報告並郵寄給相關人員。
收到通知已有一段時間沒收到報告,登入主機嘗試手動寄出,卻顯示因空間不足,寄送失敗。
資料庫的檔案未有異常,且資料庫位於外接硬碟,剩餘空間非常大。
調查過程#
檢查 Linux 空間狀況#
首先用 df -h
檢查空間狀況,卻發現剩餘空間非常少。
1
2
3
4
5
6
7
8
| # 結果示意
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 50G 50G 0 100% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 3.9G 1.2M 3.9G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/sdb1 100G 60G 35G 64% /data
/dev/sdc1 200G 150G 50G 75% /backup
|
檢查根目錄下大文件夾#
可用以下命令查看根目錄下佔用空間最大的前 20 個文件夾。
我遇到的問題出在 /var/log/mysql/mysql-gen.log
。
1
| du -ahx / | sort -rh | head -n 20
|
1
2
3
4
5
6
7
8
9
10
| # 結果示意
50G /
45G /var/log/mysql/mysql-gen.log
3G /var/log
1.2G /home/user/videos
1G /usr/lib
800M /usr/share
500M /var/cache
300M /tmp
# ...
|
分析原因#
大約6個月前,客戶請我們將 MySQL 的 general_log 開啟,並透過 rsyslog 轉拋。
同事不清楚 general_log 是什麼,也不知道 rsyslog 是即時轉拋,因此沒有設定定時清除。
簡單來說 general_log 是 MySQL 的詳細 log,會記錄所有查詢,因此會產生大量的 log。
短短6個月,就直接將剩餘空間占滿。
解決方案#
步驟 1: 使用 logrotate 定期清除日誌文件#
在 /etc/logrotate.d/mysql
中添加以下設定:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| /var/log/mysql/mysql-gen.log {
# 每天執行一次日誌輪換
daily
# 保留最近 7 份日誌
rotate 7
# 忽略不存在的文件
missingok
# 如果日誌文件為空,則不進行輪換
notifempty
# 壓縮日誌文件
compress
delaycompress
# 創建日誌文件,640 檔案權限,MySQL 使用者擁有
create 640 MySQL MySQL
# 在輪換後執行命令
postrotate
# 使用 MySQLadmin 命令刷新 MySQL 日誌,確保 MySQL 開始使用新的日誌文件
/usr/bin/mysqladmin flush-logs
endscript
}
|
步驟 2: 強制執行新設定#
1
2
3
| # -f 強制執行
# -v 顯示詳細資訊
logrotate -fv /etc/logrotate.d/mysql
|
步驟 3: 清理現有的大檔案日誌#
移除 rotate 出的 mysql-gen.log.1
文件,釋放空間。
步驟 4: 驗證結果#
再次使用 df -h
查看硬碟使用情況,確認根目錄空間已釋放。
- 若 Linux 運作異常,可檢查硬體及記憶體使用狀況。
- 使用 logrotate 定時清理日誌,避免日誌過大,占用空間。
- 在做任何設定或指令前,必須先了解指令的用途及可能產生的後果。