1. 前言
在我登錄我自己開發的產品血玉鑽的時候,我發現接口沒有數據返回,遠程登錄發現服務器也並沒有掛掉。因為我是通過pm2管理我的應用的,於是乎,我日常pm2 restart 項目,發現接口還是數據沒有返回,也沒有報錯,於是我沒有用pm2啟動項目,直接node main.js啟動項目,發現MySql Lock wait timeout exceeded 這個錯誤。
然後我又進行萬能重啟操作,重啟mysql,先systemctl stop mysqld,然後再systemctl start mysqld,這問題就出來了,啟動失敗,報如下錯誤。
<code>Starting mysqld (via systemctl): Job for mysqld.service failed because the control process exited
with
error
code. See"systemctl status mysqld.service"
and
"journalctl -xe"
for
details. [FAILED
] /<code>然後我就看我之前寫的記錄mysql的文章雲服務器Mysql安裝配置 和linux安裝mysql啟動不起來總結 這兩篇文章,果然安裝記錄的文章,發現了mysql啟動不起來的原因,如下:
<code>
Disk
is
full
writing
'./binlog.000039'
(OS
errno
28
-
No
space
left
on
device).
Waiting
for
someone
to
free
space...
Retry
in
60
secs.
Message
reprinted
in
600
secs
/<code>2. linux命令查看磁盤使用情況
通過上面我們已經知道,mysql啟動不成功的原因是因為磁盤不足。 這裡我們就先來學習下,怎麼查看linux服務器磁盤空間使用情況。
2.1 使用df -h命令查看磁盤空空間
使用df -h命令查看磁盤空間,若磁盤空間不足則清理(當然這是我解決之後的截圖,之前的磁盤滿的情況忘了截圖)。
2.2 du的用法
du命令用來查看目錄或文件所佔用磁盤空間的大小。常用選項組合為:du -sh
du常用的選項: -h:以人類可讀的方式顯示 -a:顯示目錄佔用的磁盤空間大小,還要顯示其下目錄和文件佔用磁盤空間的大小 -s:顯示目錄佔用的磁盤空間大小,不要顯示其下子目錄和文件佔用的磁盤空間大小 -c:顯示幾個目錄或文件佔用的磁盤空間大小,還要統計它們的總和 --apparent-size:顯示目錄或文件自身的大小 -l :統計硬鏈接佔用磁盤空間的大小 -L:統計符號鏈接所指向的文件佔用的磁盤空間大小 du -lh --max-depth=1: 查看當前目錄下一級子文件和子目錄佔用的磁盤容量。 du -h -x --max-depth=1:查看哪個目錄佔用過高 du -sh * | sort -n 統計當前文件夾(目錄)大小,並按文件大小排序 du -sk filename 查看指定文件大小
3. 查看佔用空間大的文件
然後用du命令查看linux文件佔用磁盤大小情況。
然後我們查到原因了,是mysql文件夾裡面就佔用了25G磁盤,總共磁盤才40G,然後在進入mysql文件夾查看
發現binglog之類的文件竟然達到了20多G。
binlog是什麼呢?
Mysql Binlog是二進制格式的日誌文件,但是不能把binlog文件等同於OS系統某目錄下的具體文件,這是狹隘的。Binlog是用來記錄Mysql內部對數據庫的改動(只記錄對數據的修改操作),主要用於數據庫的主從複製以及增量恢復。
然後我們知道這寫文件主要是記錄對數據的修改操作,主要用於數據庫的主從複製,但是我的應用並沒有用到主從複製,所以是可以刪除的。
4. mysql的binlog安全刪除
默認情況下mysql會一直保留mysql-bin文件,這樣到一定時候,磁盤可能會被撐滿,這時候是否可以刪除這些文件呢,是否可以安全刪除,是個問題。
首先要說明一下,這些文件都是mysql的日誌文件,如果不做主從複製的話,基本上是沒用的,雖然沒用,但是不建議使用rm命令刪除,這樣有可能會不安全,正確的方法是通過mysql的命令去刪除。
我們登錄mysql之後,使用命令
<code>
mysql>
reset
master;
Query
OK,
0
rows
affected
(3
min
37.65
sec)
/<code>其實關鍵的命令就是reset master;這個命令會清空mysql-bin文件。
另外如果你的mysql服務器不需要做主從複製的話,建議通過修改my.cnf文件,來設置不生成這些文件,只要刪除my.cnf中的下面一行就可以了。
<code>
log-bin
=mysql-bin /<code>如果你需要複製,最好控制一下這些日誌文件保留的天數,可以通過下面的配置設定日誌文件保留的天數:
<code>
expire_logs_days
=7
/<code>表示保留7天的日誌,這樣老日誌會自動被清理掉。
另外的方法
4.1 手動清理binlog
① 查看主庫和從庫正在使用的binlog是哪個文件
<code>
show
master
status
\Gshow
slave
status
\G \ /<code>② 在刪除binlog日誌之前,首先對binlog日誌備份,以防萬一 開始動手刪除binlog:
<code>
purge
master
logs
before
'2016-09-01 17:20:00'
; //刪除指定日期以前的日誌索引中binlog日誌文件 /<code>或
<code>
purge
master
logs
to
'mysql-bin.000022'
; //刪除指定日誌文件的日誌索引中binlog日誌文件 /<code>注意: 時間和文件名一定不可以寫錯,尤其是時間中的年和文件名中的序號,以防不小心將正在使用的binlog刪除!!!
切勿刪除正在使用的binlog!!!
使用該語法,會將對應的文件和mysql-bin.index中的對應路徑刪除。
4.2 通過設置binlog過期的時間,使系統自動刪除binlog文件
這種就是類似上面的expire_logs_days = 7
<code>mysql> show variables like
'expire_logs_days'
; +------------------+-------+| Variable_name |
Value| +------------------+-------+ |
expire_logs_days| 0 |
+------------------+-------+ mysql> set global expire_logs_days =30
; ———————————————— /<code>注意: 過期時間設置的要適當,對於主從複製,要看從庫的延遲決定過期時間,避免主庫binlog還未傳到從庫便因過期而刪除,導致主從不一致!!!
通過上面的方法之後,我們再一次查看磁盤使用情況,發現刪除binlog之後,足足多出了一半以上的磁盤空間,開心。
5. mysql擴展
5.1 innodb_file_per_table 的簡要說明
在很久很久以前也就是說還沒有innodb_file_per_table 的那個年代,所有的innodb表的數據都是保存在innodb系統表空間中的,
在有了innodb_file_per_table參數後innodb可以把每個表的數據單獨保存。單獨保存有兩方面的優勢一個是方便管理,二個是提長性能。
5.2 mysql 引用innodb_file_per_table是為了解決什麼問題
在沒有innodb_file_per_table之前所有的innodb表的數據都是統一保存到,innodb系統表空間文件中的,如果想讓mysql的行為
與innodb_file_per_table還沒有引入時的行為一致,那麼把innodb_file_per_table設置為OFF就行。
1、由於數據都統一保存到innodb系統表空間文件中,在drop table ,truncate table後表空間文件並不會進行收縮,也就是說表空間文件所佔的磁盤空間並不會因為drop table , truncate table 而釋放。
2、對於mysql來說alter table 的過程大概可以概括為 1)根據alter table 的指示創建出一張新的表 . 2)把老表的數據插入表新表中3)刪了老表. 4)把新表的表名字重命名成老表的名字;當然如今的mysql已經有inplace對上面的過程進行優化了,不過並不是所有的alter table 都支持inplace,更多關於inplace的問題在此不表了。還是回到alter table 的第2)步 由這裡可以看出系統表空間是要增大的(理由是:創建了新的表,又在向新的表中插入數據) 所以啊alter table 會導致系統表空間的進一步加大。
3、在linux系統中不允許並行的對一個文件進行寫入(innodb_flush_method=O_DIRECT的情況下是這樣的),這可能成為一個性能問題
4、對於使用innodb_file_per_table=ON的情況下,默認創建出來的ibd文件的格式是Barracuda,在這個文件格式下innodb數據行的格式就可以設置為compressed 或 dynamic 格式了。compressed 提供壓縮功能節約空間,dynamic能優化對blob,text這樣的數據類型的存儲以提升性能。
5.3 Mysql刪除數據後磁盤空間未釋放的解決辦法
官方推薦使用 OPTIMIZE TABLE命令來優化表,該命令會重新利用未使用的空間,並整理數據文件的碎片。
語法如下:
OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...
注:該命令將會整理表數據和相關的索引數據的物理存儲空間,用來減少佔用的磁盤空間,並提高訪問表時候的IO性能。但是,具體對錶產生的影響是依賴於表使用的存儲引擎的。該命令對視圖無效。
執行語句:show table status like 'table_name'查看錶信息
查詢結果中:
<code>
Index_length
代表索引的數量
Data_free
代表碎片數量
/<code>然後執行下面命令進行優化整理:
<code>mysql > optimize
table
table_name /<code>如果之前的碎片數量多,執行時間可能會久一點,執行結束後出現下面框內的數據則優化成功。
注意事項: 由於命令optimize會進行鎖表操作,所以進行優化時要避開表數據操作時間,避免影響正常業務的進行。
MySQL5.7已經推薦對於InnoDB的table使用 alter table table_name engine=innodb;語句的方式來進行表碎片優化。