在數(shù)據(jù)庫(kù)表丟失或損壞的情況下 備份你的數(shù)據(jù)庫(kù)是很重要的 如果發(fā)生系統(tǒng)崩潰 你肯定想能夠?qū)⒛愕谋肀M可能丟失最少的數(shù)據(jù)恢復(fù)到崩潰發(fā)生時(shí)的狀態(tài) 有時(shí) 正是MySQL管理員造成破壞 管理員已經(jīng)知道表以破壞 用諸如vi或Emacs等編輯器試圖直接編輯它們 這對(duì)表絕對(duì)不是件好事!備份數(shù)據(jù)庫(kù)兩個(gè)主要方法是用mysqldump程序或直接拷貝數(shù)據(jù)庫(kù)文件(如用cp cpio或tar等) 每種方法都有其優(yōu)缺點(diǎn) mysqldump與MySQL服務(wù)器協(xié)同操作 直接拷貝方法在服務(wù)器外部進(jìn)行 并且你必須采取措施保證沒(méi)有客戶正在修改你將拷貝的表 如果你想用文件系統(tǒng)備份來(lái)備份數(shù)據(jù)庫(kù) 也會(huì)發(fā)生同樣的問(wèn)題 如果數(shù)據(jù)庫(kù)表在文件系統(tǒng)備份過(guò)程中被修改 進(jìn)入備份的表文件主語(yǔ)不一致的狀態(tài) 而對(duì)以后的恢復(fù)表將失去意義 文件系統(tǒng)備份與直接拷貝文件的區(qū)別是對(duì)后者你完全控制了備份過(guò)程 這樣你能采取措施確保服務(wù)器讓表不受干擾 mysqldump比直接拷貝要慢些 mysqldump生成能夠移植到其它機(jī)器的文本文件 甚至那些有不同硬件結(jié)構(gòu)的機(jī)器上 直接拷貝文件不能移植到其它機(jī)器上 除非你正在拷貝的表使用MyISAM存儲(chǔ)格式 ISAM表只能在相似的硬件結(jié)構(gòu)的機(jī)器上拷貝 在MySQL 中引入的MyISAM表存儲(chǔ)格式解決了該問(wèn)題 因?yàn)樵摳袷绞菣C(jī)器無(wú)關(guān)的 所以直接拷貝文件可以移植到具有不同硬件結(jié)構(gòu)的機(jī)器上 只要滿足兩個(gè)條件 另一臺(tái)機(jī)器必須也運(yùn)行MySQL 或以后版本 而且文件必須以MyISAM格式表示 而不是ISAM格式 不管你使用哪種備份方法 如果你需要恢復(fù)數(shù)據(jù)庫(kù) 有幾個(gè)原則應(yīng)該遵守 以確保最好的結(jié)果 定期實(shí)施備份 建立一個(gè)計(jì)劃并嚴(yán)格遵守 讓服務(wù)器執(zhí)行更新日志 當(dāng)你在崩潰后需要恢復(fù)數(shù)據(jù)時(shí) 更新日志將幫助你 在你用備份文件恢復(fù)數(shù)據(jù)到備份時(shí)的狀態(tài)后 你可以通過(guò)運(yùn)行更新日志中的查詢?cè)俅芜\(yùn)用備份后面的修改 這將數(shù)據(jù)庫(kù)中的表恢復(fù)到崩潰發(fā)生時(shí)的狀態(tài) 以文件系統(tǒng)備份的術(shù)語(yǔ)講 數(shù)據(jù)庫(kù)備份文件代表完全傾倒(full dump) 而更新日志代表漸進(jìn)傾倒(incremental dump) 使用一種統(tǒng)一的和易理解的備份文件命名機(jī)制 象backup buckup 等不是特別有意義 當(dāng)實(shí)施你的恢復(fù)時(shí) 你將浪費(fèi)時(shí)間找出文件里是什么東西 你可能發(fā)覺(jué)用數(shù)據(jù)庫(kù)名和日期構(gòu)成備份文件名會(huì)很有用 例如 %mysqldump samp_db /usr/archives/mysql/samp_db %mysqldump menagerie /usr/archives/mysql/menagerie 你可能想在生成備份后壓縮它們 備份一般都很大!你也需要讓你的備份文件有過(guò)期期限以避免它們填滿你的磁盤 就象你讓你的日志文件過(guò)期那樣 用文件系統(tǒng)備份備份你的備份文件 如果遇上了一個(gè)徹底崩潰 不僅清除了你的數(shù)據(jù)目錄 也清除了包含你的數(shù)據(jù)庫(kù)備份的磁盤驅(qū)動(dòng)器 你將真正遇上了麻煩 也要備份你的更新日志 將你的備份文件放在不同于用于你的數(shù)據(jù)庫(kù)的文件系統(tǒng)上 這將降低由于生成備份而填滿包含數(shù)據(jù)目錄的文件系統(tǒng)的可能性 用于創(chuàng)建備份的技術(shù)同樣對(duì)拷貝數(shù)據(jù)庫(kù)到另一臺(tái)機(jī)器有用 最常見(jiàn)地 一個(gè)數(shù)據(jù)庫(kù)被轉(zhuǎn)移到了運(yùn)行在另一臺(tái)主機(jī)上的服務(wù)器 但是你也可以將數(shù)據(jù)轉(zhuǎn)移到同一臺(tái)主機(jī)上的另一個(gè)服務(wù)器 使用mysqldump備份和拷貝數(shù)據(jù)庫(kù) 當(dāng)你使用mysqldumo程序產(chǎn)生數(shù)據(jù)庫(kù)備份文件時(shí) 缺省地 文件內(nèi)容包含創(chuàng)建正在傾倒的表的CREATE語(yǔ)句和包含表中行數(shù)據(jù)的INSERT語(yǔ)句 換句話說(shuō) mysqldump產(chǎn)生的輸出可在以后用作mysql的輸入來(lái)重建數(shù)據(jù)庫(kù) 你可以將整個(gè)數(shù)據(jù)庫(kù)傾倒進(jìn)一個(gè)單獨(dú)的文本文件中 如下 %mysqldump samp_db /usr/archives/mysql/samp_db 輸出文件的開(kāi)頭看起來(lái)象這樣 # MySQL Dump ## Host: localhost Database: samp_db# # Server version alpha log## Table structure for table absence #CREATE TABLE absence(student_id int( ) unsigned DEFAULT NOT NULL date date DEFAULT NOT NULL PRIMARY KEY (student_id date));## Dumping data for table absence #INSERT INTO absence VALUES ( );INSERT INTO absence VALUES ( );INSERT INTO absence VALUES ( ); 文件剩下的部分有更多的INSERT和CREATE TABLE語(yǔ)句組成 如果你想壓縮備份 使用類似如下的命令 %mysqldump samp_db | gzip /usr/archives/mysql/samp_db gz如果你要一個(gè)龐大的數(shù)據(jù)庫(kù) 輸出文件也將很龐大 可能難于管理 如果你愿意 你可以在mysqldump命令行的數(shù)據(jù)庫(kù)名后列出單獨(dú)的表名來(lái)傾到它們的內(nèi)容 這將傾倒文件分成較小 更易于管理的文件 下例顯示如何將samp_db數(shù)據(jù)庫(kù)的一些表傾到進(jìn)分開(kāi)的文件中 %mysqldump samp_db student score event absence grapbook sql%mysqldump samp_db member president hist league sql如果你生成準(zhǔn)備用于定期刷新另一個(gè)數(shù)據(jù)庫(kù)內(nèi)容的備份文件 你可能想用 add drop table選項(xiàng) 這告訴服務(wù)器將DROP TABLE IF EXISTS語(yǔ)句寫入備份文件 然后 當(dāng)你取出備份文件并把它裝載進(jìn)第二個(gè)數(shù)據(jù)庫(kù)時(shí) 如果表已經(jīng)存在 你不會(huì)得到一個(gè)錯(cuò)誤 如果你倒出一個(gè)數(shù)據(jù)庫(kù)以便能把數(shù)據(jù)庫(kù)轉(zhuǎn)移到另一個(gè)服務(wù)器 你甚至不必創(chuàng)建備份文件 要保證數(shù)據(jù)庫(kù)存在于另一臺(tái)主機(jī) 然后用管道傾倒數(shù)據(jù)庫(kù) 這樣mysql能直接讀取mysqldump的輸出 例如 你想從主機(jī)拷貝數(shù)據(jù)庫(kù)samp_db到 可以這樣很容易做到 %mysqladmin h create samp_db%mysqldump samp_db | mysql h samp_db以后 如果你想再次刷新上的數(shù)據(jù)庫(kù) 跳過(guò)mysqladmin命令 但要對(duì)mysqldump加上 add drop table以避免的得到表已存在的錯(cuò)誤 %mysqldump add drop table samp_db | mysql h samp_dbmysqldump其它有用的選項(xiàng)包括 flush logs和 lock tables組合將對(duì)你的數(shù)據(jù)庫(kù)檢查點(diǎn)有幫助 lock tables鎖定你正在傾倒的所有表 而 flush logs關(guān)閉并重新打開(kāi)更新日志文件 新的更新日志將只包括從備份點(diǎn)起的修改數(shù)據(jù)庫(kù)的查詢 這將設(shè)置你的更新日志檢查點(diǎn)位備份時(shí)間 (然而如果你有需要執(zhí)行個(gè)更新的客戶 鎖定所有表對(duì)備份期間的客戶訪問(wèn)不是件好事 )如果你使用 flush logs設(shè)置檢查點(diǎn)到備份時(shí) 有可能最好是傾倒整個(gè)數(shù)據(jù)庫(kù) 如果你傾倒單獨(dú)的文件 較難將更新日志檢查點(diǎn)與備份文件同步 在恢復(fù)期間 你通常按數(shù)據(jù)庫(kù)為基礎(chǔ)提取更新日志內(nèi)容 對(duì)單個(gè)表沒(méi)有提取更新的選擇 所以你必須自己提取它們 缺省地 mysqldump在寫入前將一個(gè)表的整個(gè)內(nèi)容讀進(jìn)內(nèi)存 這通常確實(shí)不必要 并且實(shí)際上如果你有一個(gè)大表 幾乎是失敗的 你可用 quick選項(xiàng)告訴mysqldump只要它檢索出一行就寫出每一行 為了進(jìn)一步優(yōu)化傾倒過(guò)程 使用 opt而不是 quick opt選項(xiàng)打開(kāi)其它選項(xiàng) 加速數(shù)據(jù)的傾倒和把它們讀回 用 opt實(shí)施備份可能是最常用的方法 因?yàn)閭浞菟俣壬系膬?yōu)勢(shì) 然而 要警告你 opt選項(xiàng)確實(shí)有代價(jià) opt優(yōu)化的是你的備份過(guò)程 不是其他客戶對(duì)數(shù)據(jù)庫(kù)的訪問(wèn) opt選項(xiàng)通過(guò)一次鎖定所有表阻止任何人更新你正在傾倒的任何表 你可在一般數(shù)據(jù)庫(kù)訪問(wèn)上很容易看到其效果 當(dāng)你的數(shù)據(jù)庫(kù)一般非常頻繁地使用 只是一天一次地調(diào)節(jié)備份 一個(gè)具有 opt的相反效果的選項(xiàng)是 dedayed 該選項(xiàng)使得mysqldump寫出INSERT DELAYED語(yǔ)句而不是INSERT語(yǔ)句 如果你將數(shù)據(jù)文件裝入另一個(gè)數(shù)據(jù)庫(kù)并且你想是這個(gè)操作對(duì)可能出現(xiàn)在該數(shù)據(jù)庫(kù)中的查詢的影響最小 delayed對(duì)此很有幫助 press選項(xiàng)在你拷貝數(shù)據(jù)庫(kù)到另一臺(tái)機(jī)器上時(shí)很有幫助 因?yàn)樗鼫p少網(wǎng)絡(luò)傳輸字節(jié)的數(shù)量 下面有一個(gè)例子 注意到 press對(duì)與遠(yuǎn)端主機(jī)上的服務(wù)器通信的程序才給出 而不是對(duì)與本地主機(jī)連接的程序 %mysqldump opt samp_db | mysql press h samp_dbmysqldump有很多選項(xiàng) 詳見(jiàn)《MySQL參考手冊(cè)》 使用直接拷貝數(shù)據(jù)庫(kù)的備份和拷貝方法 另一種不涉及mysqldump備份數(shù)據(jù)庫(kù)和表的方式是直接拷貝數(shù)據(jù)庫(kù)表文件 典型地 這用諸如cp tar或cpio實(shí)用程序 本文的例子使用cp 當(dāng)你使用一種直接備份方法時(shí) 你必須保證表不在被使用 如果服務(wù)器在你則正在拷貝一個(gè)表時(shí)改變它 拷貝就失去意義 保證你的拷貝完整性的最好方法是關(guān)閉服務(wù)器 拷貝文件 然后重啟服務(wù)器 如果你不想關(guān)閉服務(wù)器 要在執(zhí)行表檢查的同時(shí)鎖定服務(wù)器 如果服務(wù)器在運(yùn)行 相同的制約也適用于拷貝文件 而且你應(yīng)該使用相同的鎖定協(xié)議讓服務(wù)器 安靜下來(lái) 假設(shè)服務(wù)器關(guān)閉或你已經(jīng)鎖定了你想拷貝的表 下列顯示如何將整個(gè)samp_db數(shù)據(jù)庫(kù)備份到一個(gè)備份目錄(DATADIR表示服務(wù)器的數(shù)據(jù)目錄) %cd DATADIR%cp r samp_db /usr/archive/mysql單個(gè)表可以如下備份 %cd DATADIR/samp_db%cp member * /usr/archive/mysql/samp_db%cp score * /usr/archive/mysql/samp_db 當(dāng)你完成了備份時(shí) 你可 lishixinzhi/Article/program/MySQL/201311/29384
尚志網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),尚志網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為尚志1000+提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設(shè)要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的尚志做網(wǎng)站的公司定做!
一、背景
近期,公司RDS云產(chǎn)品的MySQL Server版本進(jìn)行升級(jí),由目前使用的5.7.26版本升級(jí)到最新版本5.7.31;升級(jí)后測(cè)試同學(xué)發(fā)現(xiàn):在MySQL創(chuàng)建用戶后,5.7.31版本重新啟動(dòng)集群會(huì)出現(xiàn)啟動(dòng)失敗的現(xiàn)象;而5.7.26版本在相同測(cè)試場(chǎng)景下是正常啟動(dòng)的。這到底是為什么呢?
二、問(wèn)題復(fù)現(xiàn)
2.1 實(shí)驗(yàn)環(huán)境
2.2 操作步驟
按照測(cè)試同學(xué)的測(cè)試步驟,首先創(chuàng)建一個(gè)用戶:
然后關(guān)閉mysqld;這里需要介紹一下,我們集群的關(guān)閉方式是如下方式:
這種方式的內(nèi)部實(shí)現(xiàn)類似于kill -9模式。所以我在線下環(huán)境使用kill -9的方式來(lái)復(fù)現(xiàn),操作如下:
然后重啟mysqld,操作如下:
此時(shí)問(wèn)題復(fù)現(xiàn)了,mysqld啟動(dòng)失敗,我們查看了下error日志,信息如下:
根據(jù)報(bào)錯(cuò)信息可以看出:MySQL的權(quán)限系統(tǒng)表發(fā)生了損壞,導(dǎo)致了mysqld啟動(dòng)失??;由于在MySQL 5.7及其之前版本該表是MyISAM引擎,且該引擎不支持事務(wù),所以在mysqld異常崩潰會(huì)導(dǎo)致該類型引擎表的損壞;但在mysqld啟動(dòng)時(shí)是有參數(shù)控制MyISAM引擎的恢復(fù)模式,且該參數(shù)在我們產(chǎn)品中也配置到了my.cnf中,如下所示:
2.3 參數(shù)解析
對(duì)于該參數(shù)的官方文檔的解釋如下:
設(shè)置MyISAM存儲(chǔ)引擎恢復(fù)模式。選項(xiàng)值是OFF、DEFAULT、BACKUP、FORCE或QUICK的值的任意組合。如果指定多個(gè)值,請(qǐng)用逗號(hào)分隔。指定不帶參數(shù)的選項(xiàng)與指定DEFAULT相同,指定顯式值" "將禁用恢復(fù)(與OFF值相同)。如果啟用了恢復(fù),則mysqld每次打開(kāi)MyISAM表時(shí),都會(huì)檢查該表是否標(biāo)記為已崩潰或未正確關(guān)閉。(只有在禁用外部鎖定的情況下運(yùn)行,最后一個(gè)選項(xiàng)才起作用。)在這種情況下,mysqld在表上運(yùn)行檢查。如果表已損壞,mysqld將嘗試對(duì)其進(jìn)行修復(fù)。
服務(wù)器自動(dòng)修復(fù)表之前,它將有關(guān)修復(fù)的注釋寫到錯(cuò)誤日志中。如果您希望能夠在無(wú)需用戶干預(yù)的情況下從大多數(shù)問(wèn)題中恢復(fù),則應(yīng)使用選項(xiàng)BACKUP,F(xiàn)ORCE。即使某些行將被刪除,這也會(huì)強(qiáng)制修復(fù)表,但是它將舊的數(shù)據(jù)文件保留為備份,以便您以后可以檢查發(fā)生了什么。
全局變量,只讀變量,默認(rèn)為OFF。
三、問(wèn)題修復(fù)
這類MySQL用戶表?yè)p耗的問(wèn)題解決方式也是有多種,我這里列舉其中一種:
(1)my.cnf中的[mysqld]標(biāo)簽下添加skip_grant_tables,啟動(dòng)時(shí)跳過(guò)加載系統(tǒng)字典。
(2)重啟mysqld,然后修復(fù)mysql schema下的所有表。
(3)在[mysqld]標(biāo)簽下注釋或刪除掉skip_grant_tables,然后重啟mysqld。
此時(shí)mysqld是可以正常啟動(dòng)的,無(wú)異常。
四、深入排查
在產(chǎn)品化中,以上修復(fù)方式很不優(yōu)雅,只是作為臨時(shí)的解決方案;并且也存在一些令人疑惑的點(diǎn):
帶著這些疑問(wèn),我們繼續(xù)排查出現(xiàn)該現(xiàn)象的原因;此時(shí)Google也沒(méi)有找到一些有效的信息,那么只能通過(guò)MySQL源代碼來(lái)尋找一些答案。
首先需要下載mysql 5.7.31版本的源代碼,并搭建mysql debug環(huán)境;具體步驟可以自動(dòng)Google搜索一下,本文就不再贅述了。
在源代碼中搜索一下關(guān)鍵詞,用于打斷點(diǎn)的位置,然后進(jìn)行調(diào)試:
定位到相關(guān)代碼,大概是sql/mysqld.cc的4958行,且存在if條件判斷,此時(shí)我們開(kāi)始調(diào)試:
通過(guò)以上調(diào)試信息,可以判斷出acl_init函數(shù)返回的值為真;此時(shí)我們查看該函數(shù)的代碼 (sql/auth/sql_auth_cache.cc:1365):
根據(jù)該函數(shù)的注釋發(fā)現(xiàn):該函數(shù)是初始化負(fù)責(zé)用戶/數(shù)據(jù)庫(kù)級(jí)特權(quán)檢查的結(jié)構(gòu),并從mysql schema中的表中為其加載特權(quán)信息;且return值為1代表的是初始化權(quán)限失敗。
此后開(kāi)始逐步調(diào)試,觀察return相關(guān)信息,當(dāng)調(diào)試到lock_table_names函數(shù)時(shí),我們發(fā)現(xiàn)在Phase 3時(shí)return值為true,且根據(jù)代碼注釋發(fā)現(xiàn)true代表是Failure;具體代碼如下(sql/sql_base.cc:5549):
調(diào)試信息如下:
可以看到flags的值為0,而MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK為宏定義值0x1000,與flags的值 做按位與操作,結(jié)果自然也是0,當(dāng)然MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY也是如此;need_global_read_lock_protection是bool類型值,代表是否需要全局讀鎖的保護(hù),這個(gè)值是在table- mdl_request.type不為MDL_SHARED_READ_ONLY發(fā)生改變;check_readonly函數(shù)相關(guān)信息 下面概述。
此時(shí)也查看了下MySQL 5.7.26版本代碼作為對(duì)比,發(fā)現(xiàn)lock_table_names函數(shù)下的Phase 3后的部分代 碼是在5.7.29版本后新增的。如果是git clone的MySQL代碼可以用git blame命令查詢文件變化的信息:
上述展示的信息中,最左側(cè)的列值為commit id為05824063和0405ebee,有興趣的同學(xué)可以詳細(xì)看下。
此功能解決的問(wèn)題是 BUG#28438114: SET READ_ONLY=1 SOMETIMES DOESN'T BLOCK CONCURRENT DDL.;當(dāng)然這個(gè)代碼的變更功能也在5.7 Release Notes中有所體現(xiàn),如下所示( m/doc/relnotes/mysql/5.7/en/news-5-7-29.html ):
最后我們?cè)俨榭聪耤heck_readonly函數(shù),該函數(shù)是基于read_only和super_read_only狀態(tài)執(zhí)行標(biāo)準(zhǔn)化檢查,是禁止(TRUE)還是允許(FALSE)操作。代碼如下(sql/auth/sql_authorization.cc:489):
此時(shí)第一反應(yīng)就是去檢查my.cnf中是否包含read_only相關(guān)參數(shù),檢查之后發(fā)現(xiàn)確實(shí)是使用了該參數(shù), 如下:
此時(shí)注釋掉該參數(shù),然后再次啟動(dòng)mysqld,發(fā)現(xiàn)MyISAM表可以自動(dòng)修復(fù),且正常啟動(dòng);error log信息如下:
由于docker一些限制,我們?cè)趍ysqld啟動(dòng)會(huì)涉及兩次;所以解決該問(wèn)題的方式為:第一次mysqld的啟動(dòng)時(shí)先關(guān)閉read_only參數(shù),第二次啟動(dòng)時(shí)開(kāi)啟read_only參數(shù)。之所以選擇默認(rèn)開(kāi)啟read_only參數(shù), 是為了避免在mysqld啟動(dòng)后,選主邏輯未完成時(shí)的保護(hù)措施;當(dāng)然選主完成后,會(huì)自動(dòng)對(duì)master執(zhí)行 set global read_only=0 操作。
五、總結(jié)
六、附錄
調(diào)試的棧幀信息如下,有興趣的小伙伴可以研究下:
熟悉MySQL體系結(jié)構(gòu)和innodb存儲(chǔ)引擎工作原理;以及MySQL備份恢復(fù)、復(fù)制、數(shù)據(jù)遷移等技術(shù);專注于MySQL、MariaDB開(kāi)源數(shù)據(jù)庫(kù),喜好開(kāi)源技術(shù)。
原文鏈接:
有兩種方法,一種方法使用mysql的check table和repair table 的sql語(yǔ)句,另一種方法是使用MySQL提供的多個(gè)myisamchk, isamchk數(shù)據(jù)檢測(cè)恢復(fù)工具。
前者使用起來(lái)比較簡(jiǎn)便。推薦使用。
1、check table 和 repair table 登陸mysql 終端: mysql -uxxxxx -p dbname check table tabTest;
如果出現(xiàn)的結(jié)果說(shuō)Status是OK,則不用修復(fù),如果有Error,可以用: repair table tabTest; 進(jìn)行修復(fù),修復(fù)之后可以在用check table命令來(lái)進(jìn)行檢查。
在新版本的phpMyAdmin里面也可以使用check/repair的功能。
2. myisamchk, isamchk 其中myisamchk適用于MYISAM類型的數(shù)據(jù)表,而isamchk適用于ISAM類型的數(shù)據(jù)表。
這兩條命令的主要參數(shù)相同,一般新的系統(tǒng)都使用MYISAM作為缺省的數(shù)據(jù)表類型,這里以myisamchk為例子進(jìn)行說(shuō)明。
當(dāng)發(fā)現(xiàn)某個(gè)數(shù)據(jù)表出現(xiàn)問(wèn)題時(shí)可以使用: myisamchk tablename.MYI 進(jìn)行檢測(cè),如果需要修復(fù)的話,可以使用: myisamchk -of tablename.MYI 關(guān)于myisamchk的詳細(xì)參數(shù)說(shuō)明,可以參見(jiàn)它的使用幫助。
需要注意的時(shí)在進(jìn)行修改時(shí)必須確保MySQL服務(wù)器沒(méi)有訪問(wèn)這個(gè)數(shù)據(jù)表,保險(xiǎn)的情況下是最好在進(jìn)行檢測(cè)時(shí)把MySQL服務(wù)器Shutdown掉。
2、另外可以把下面的命令放在你的rc.local里面啟動(dòng)MySQL服務(wù)器前: [ -x /tmp/mysql.sock ] /pathtochk/myisamchk -of /DATA_DIR/*/*.MYI 。
其中的/tmp/mysql.sock是MySQL監(jiān)聽(tīng)的Sock文件位置,對(duì)于使用RPM安裝的用戶應(yīng)該是/var/lib/mysql/mysql.sock,對(duì)于使用源碼安裝則是/tmp/mysql.sock可以根據(jù)自己的實(shí)際情況進(jìn)行變更,而pathtochk則是myisamchk所在的位置,DATA_DIR是你的MySQL數(shù)據(jù)庫(kù)存放的位置。
需要注意的是,如果你打算把這條命令放在你的rc.local里面,必須確認(rèn)在執(zhí)行這條指令時(shí)MySQL服務(wù)器必須沒(méi)有啟動(dòng)!
最后檢測(cè)修復(fù)所有數(shù)據(jù)庫(kù)(表)。
可以使用語(yǔ)句檢查表。如果結(jié)果的msg_text部分是好的,那么你的表是健康的。反之,則表明mysql數(shù)據(jù)庫(kù)中的表有損壞。另外有些厲害的高手一額可以通過(guò)運(yùn)行腳本來(lái)檢測(cè)。
MyISAM?表可以采用以下方法進(jìn)行修復(fù)?:使用?reapair table?或myisamchk?來(lái)修復(fù)。如果修復(fù)無(wú)效,采用備份恢復(fù)表。
階段1?:檢查你的表
如果你有很多時(shí)間,運(yùn)行myisamchk *.MYI?或myisamchk -e *.MYI?。使用-s?(沉默)選項(xiàng)禁止不必要的信息。如果mysqld?服務(wù)器處于宕機(jī)狀態(tài),應(yīng)使用--update-state?選項(xiàng)來(lái)告訴myisamchk?將表標(biāo)記為'?檢查過(guò)的'?。
你必須只修復(fù)那些myisamchk?報(bào)告有錯(cuò)誤的表。對(duì)這樣的表,繼續(xù)到階段2?。如果在檢查時(shí),你得到奇怪的錯(cuò)誤(?例如out of memory?錯(cuò)誤)?,或如果myisamchk?崩潰,到階段3?。
階段2?:簡(jiǎn)單安全的修復(fù)
注釋:如果想更快地進(jìn)行修復(fù),當(dāng)運(yùn)行myisamchk?時(shí),你應(yīng)將sort_buffer_size?和Key_buffer_size?變量的值設(shè)置為可用內(nèi)存的大約25%?。
首先,試試myisamchk -r -q tbl_name(-r -q?意味著“?快速恢復(fù)模式”)?。這將試圖不接觸數(shù)據(jù)文件來(lái)修復(fù)索引文件。如果數(shù)據(jù)文件包含它應(yīng)有的一切內(nèi)容和指向數(shù)據(jù)文件內(nèi)正確地點(diǎn)的刪除連接,這應(yīng)該管用并且表可被修復(fù)。開(kāi)始修復(fù)下一張表。否則,執(zhí)行下列過(guò)程:
在繼續(xù)前對(duì)數(shù)據(jù)文件進(jìn)行備份。使用myisamchk -r tbl_name(-r?意味著“?恢復(fù)模式”)?。這將從數(shù)據(jù)文件中刪除不正確的記錄和已被刪除的記錄并重建索引文件。
如果前面的步驟失敗,使用myisamchk --safe-recover tbl_name?。安全恢復(fù)模式使用一個(gè)老的恢復(fù)方法,處理常規(guī)恢復(fù)模式不行的少數(shù)情況(?但是更慢)?。如果在修復(fù)時(shí),你得到奇怪的錯(cuò)誤(?例如out of memory?錯(cuò)誤)?,或如果myisamchk?崩潰,到階段3?。
階段3?:困難的修復(fù)
只有在索引文件的第一個(gè)16K?塊被破壞,或包含不正確的信息,或如果索引文件丟失,你才應(yīng)該到這個(gè)階段。在這種情況下,需要?jiǎng)?chuàng)建一個(gè)新的索引文件。按如下步驟操做:
把數(shù)據(jù)文件移到安全的地方。使用表描述文件創(chuàng)建新的(?空)?數(shù)據(jù)文件和索引文件:
shell mysql db_name
mysql SET AUTOCOMMIT=1;
mysql TRUNCATE TABLE tbl_name;
mysql quit
如果你的MySQL?版本沒(méi)有TRUNCATE TABLE?,則使用DELETE FROM tbl_name?。將老的數(shù)據(jù)文件拷貝到新創(chuàng)建的數(shù)據(jù)文件之中。回到階段2??,F(xiàn)在myisamchk -r -q?應(yīng)該工作了。你還可以使用REPAIR TABLE tbl_name USE_FRM?,將自動(dòng)執(zhí)行整個(gè)程序。
階段4?:非常困難的修復(fù)
只有.frm?描述文件也破壞了,你才應(yīng)該到達(dá)這個(gè)階段。這應(yīng)該從未發(fā)生過(guò),因?yàn)樵诒肀粍?chuàng)建以后,描述文件就不再改變了。
從一個(gè)備份恢復(fù)描述文件然后回到階段3?。你也可以恢復(fù)索引文件然后回到階段2?。對(duì)后者,你應(yīng)該用myisamchk -r?啟動(dòng)。
如果你沒(méi)有進(jìn)行備份但是確切地知道表是怎樣創(chuàng)建的,在另一個(gè)數(shù)據(jù)庫(kù)中創(chuàng)建表的一個(gè)拷貝。刪除新的數(shù)據(jù)文件,然后從其他數(shù)據(jù)庫(kù)將描述文件和索引文件移到破壞的數(shù)據(jù)庫(kù)中。這樣提供了新的描述和索引文件,但是讓.MYD?數(shù)據(jù)文件獨(dú)自留下來(lái)了?;氐诫A段2并且嘗試重建索引文件。
損壞mysql數(shù)據(jù)表的索引
mysql表索引被破壞的問(wèn)題及解決
下午上班,驚聞我的dedecms的網(wǎng)站出問(wèn)題了,訪問(wèn)一看,果然全屏報(bào)錯(cuò),檢查mysql日志,錯(cuò)誤信息為:
Table '.\dedecmsv4\dede_archives' is marked as crashed and should be repaired
提示說(shuō)cms的文章表dede_archives被標(biāo)記有問(wèn)題,需要修復(fù)。于是趕快恢復(fù)歷史數(shù)據(jù),上網(wǎng)查找原因。最終將問(wèn)題解決。解決方法如下:
找到mysql的安裝目錄的bin/myisamchk工具,在命令行中輸入:
myisamchk -c -r ../data/dedecmsv4/dede_archives.MYI
然后myisamchk 工具會(huì)幫助你恢復(fù)數(shù)據(jù)表的索引。重新啟動(dòng)mysql,問(wèn)題解決。
問(wèn)題分析:
1、錯(cuò)誤產(chǎn)生原因,有網(wǎng)友說(shuō)是頻繁查詢和更新dede_archives表造成的索引錯(cuò)誤,因?yàn)槲业捻?yè)面沒(méi)有靜態(tài)生成,而是動(dòng)態(tài)頁(yè)面,因此比較同意
這種說(shuō)法。還有說(shuō)法為是MYSQL數(shù)據(jù)庫(kù)因?yàn)槟撤N原因而受到了損壞,如:數(shù)據(jù)庫(kù)服務(wù)器突發(fā)性的斷電、在提在數(shù)據(jù)庫(kù)表提供服務(wù)時(shí)對(duì)表的原文件