centos/windows服務器,Mysql數據庫表結構損壞-已解決
【問題原因】服務器突然斷電
【故障報告】數據庫表結構損壞
【解決思路】進入強制恢復模式,備份庫表及數據重建
故障發現
周末公司斷電,周一啟動數據庫就直接報錯了
查看日誌
上面標記的log,明確表示是非正常關機(InnoDB: Database was not shutdown normally!)導致表結構損壞了,並且在最後給出了三種修復建議:
1)權限問題。我的文件無此類問題,略過該方案
2)跳過當前表恢復。我出錯的表比較重要,全額無法通過備份恢復,所以該方案也不合適
3)調整強制恢復級別,強制修復表結構。我後續的處理,使用了選擇了該方案。
備註:斷電時往往數據結構都還是好的,只是mysql事務未完成,有壞的數據在這裡,所以有錯誤。 理論上只要修復表結構、去除壞的數據,mysql就可以正常恢復了。
處理故障
如上所述,權衡之後,我採用了強制啟動+導出數據重建的方式。
調整強制恢復級別
找到配置進入編輯模式:# vim /etc/my.cnf
在[mysqld]配置項下面配置(配置前需要檢查,如果配置文件中已有該配置,將值改為6;如果沒有則新增這項配置。)
配置文件中調整級別:(配置前需要檢查,如果配置文件中已有該配置,將值改為6;如果沒有則新增這項配置。)
因為之前也遇到過類似問題,低級別恢復失敗了。所以我這裡直接使用級別6:跳過啟動檢測直接進行庫表重建。
如果是其他情況的啟動異常,具體問題分析後再確定採用哪個級別。
innodb_force_recovery參數說明:
影響整個InnoDB存儲引擎的恢復狀況,默認值為0,表示當需要恢復時執行所有的恢復操作。 當不能進行有效的恢復操作時,MySQL有可能無法啟動,並記錄下錯誤日誌。
innodb_force_recovery可以設置為1-6,大的數字包含前面所有數字的影響。 當設置參數值大於0後,可以對錶進行select/create/drop操作,但insert/update/delete這類操作是不允許的。
1 (SRV_FORCE_IGNORE_CORRUPT):忽略檢查到的corrupt頁
2 (SRV_FORCE_NO_BACKGROUND):阻止主線程的運行,如主線程需要執行full purge操作,會導致crash
3 (SRV_FORCE_NO_TRX_UNDO):不執行事務回滾操作。
4 (SRV_FORCE_NO_IBUF_MERGE):不執行插入緩衝的合併操作。
5 (SRV_FORCE_NO_UNDO_LOG_SCAN):不查看重做日誌,InnoDB存儲引擎會將未提交的事務視為已提交。
6 (SRV_FORCE_NO_LOG_REDO):不執行前滾的操作。
啟動MySQL
配置改好後,就可以啟動了。
啟動方式選擇常用的即可,但不能重複執行,否則提示進程已存在。
/etc/init.d/mysql start(在centos7.0以上版本已被systemctl start mysqld.service替代)
或者
service mysql start
正常啟動後,注意此時我們只是跳過了啟動檢查,表數據仍然是壞的。新的數據讀寫操作進來,仍然可能會出錯,甚至導致臟數據滾雪球般放大。因此需要修複數據
修複數據文件
修複數據採用的是導出後重建。
導出數據方式一
使用mysqldump命令導出:
如果數據順利導出了,可以直接查看下一節重建。
導出數據方式二
使用navicat數據庫連接工具遠程連接數據庫。
常見問題
提示密碼過期
操作時出現了密碼過期的提示:
嘗試直接登錄數據庫後,沒問題,但任何操作都會提示重設密碼:
原因暫時不清楚,畢竟只是斷電,沒有數據庫升級或其他動作。我直接按提示重設密碼
能正常讀了,接着執行備份:
執行命令:mysqldump -uroot -p –default-character-set=utf8 acc > ./acc.sql
輸入密碼,備份成功。
如果損壞的是MySQL系統表,無法dump
重建
此時數據已備份好,最大的風險已經沒有了。
為了保險起見,接下來的操作前,可以把數據文件備份。
zip -r mysql_bak.zip /var/lib/mysql 或者直接將MySQL家目錄改名(因為目前數據庫已停止,不需要關閉數據庫) mv /var/lib/mysql /var/lib/mysql_bak-user-date
有的人建議直接直接物理刪除目錄和裏面的frm與ibd文件,找到mysql的data目錄,找到目標庫,刪除整個目錄,但是我沒有成功。
我建議直接完全卸載mysql,直接重裝數據庫,因為我們現在最重要的數據已經備份出來了。這種方法百試不爽,從來沒有失敗過。
卸載數據庫(注意使用腳本前修改相應的目錄路徑)
#!/bin/bash
#SelfDir
SelfDir=$(cd "$(dirname "$0")";pwd)
echo "cerrent path is :${SelfDir}"
mysql='mysql'
if [ `rpm -qa | grep -i $mysql | wc -l` -ne 0 ]
then
echo " installed mysql "
service mysql stop
EXISTS_RPMS=`rpm -qa | grep -i mysql`
echo ${EXISTS_RPMS}
for RPM in ${EXISTS_RPMS}
do
rpm -e --nodeps ${RPM}
done
## 刪除殘留文件
rm -fr /usr/lib/mysql
rm -fr /usr/include/mysql
rm -f /etc/my.cnf
rm -fr /var/lib/mysql
rm -f /root/.mysql_secret
else
echo "start install mysql ...."
fi
echo 'finished!'
重裝MYSQL(這裡就不演示了,需要安裝之前部署的mysql版本,可以在網上查mysql安裝部署)
導入備份數據
將my.cnf中的innodb_force_recovery配置改為0或直接刪掉(無該配置項時MySQL默認為0)
然後重建數據庫
成功完成還原。
啟動應用服務正常,數據庫訪問正常。
整個恢復過程基本完成。
windwos服務器的恢複流程與上述一樣,只是服務的啟停方式,文件後綴名,卸載安裝操作不一樣而已
windwos啟停mysql net start/stop mysql或者到「服務」中啟動,停止
windwos配置文件 my.ini


