在網(wǎng)站運(yùn)行過(guò)程中,有時(shí)會(huì)連接數(shù)據(jù)庫(kù)失敗的情況,筆者經(jīng)過(guò)檢測(cè),發(fā)現(xiàn)是后臺(tái)數(shù)據(jù)庫(kù)中某些表的結(jié)構(gòu)損壞造成的。這是因?yàn)閷?duì)于“.FRM”文件來(lái),因?yàn)槠浯鎯?chǔ)著表的結(jié)構(gòu)信息,一旦其損壞,將造成無(wú)法讀取表中數(shù)據(jù)的情況。其修復(fù)策略是先將存儲(chǔ)數(shù)據(jù)的“.MYI”和“.MYD”文件復(fù)制到其他目錄中存儲(chǔ)起來(lái),之后在數(shù)據(jù)庫(kù)中重建同名的表,助于表結(jié)構(gòu)要相同。將“.MYI”和“.MYD”文件復(fù)制回來(lái),登錄數(shù)據(jù)庫(kù)執(zhí)行“repair table”命令,執(zhí)行修復(fù)操作,最后查看修復(fù)結(jié)果。這里使用相關(guān)的例子,來(lái)說(shuō)明解決的方法。
例如,在MySQL中存在名為“shujku1”的庫(kù),在該庫(kù)中存在名為“sampletb”的 表。 進(jìn) 入“/var/lib/mysql/shujuku1”目 錄,執(zhí)行“l(fā)s”命令,卻沒(méi)有發(fā)現(xiàn)“sampletb.frm”文件。當(dāng)執(zhí)行“mysql -p”命令登錄進(jìn)來(lái)。執(zhí)行“use shujuku1;”命令進(jìn)入該數(shù)據(jù)庫(kù),執(zhí)行“show tables;”命 令,會(huì)發(fā)現(xiàn)“sampletb”表并不存在。當(dāng)執(zhí)行“select * from sampletb;”之類(lèi)的命令,MySQL會(huì)顯示“ERROR 1146(42S02)”之類(lèi)的錯(cuò)誤信息。
為此,可按照上面的方法,將“sampletb.myi” 和“sampletb.myd” 移 動(dòng) 到別處,在“shujuku1”數(shù)據(jù)庫(kù)中使用“create table sampletb”命令創(chuàng)建同名的表,結(jié)構(gòu)必須相同,相當(dāng)于重建“sampletb.frm”文件。將上述文件復(fù)制回來(lái),替換掉新創(chuàng)建的文件,登錄到數(shù)據(jù)庫(kù),執(zhí)行“repair table sampletb;”命令,會(huì)重建“sampletb.frm”和上述文件之間的關(guān)系。
某次因?yàn)榉?wù)器異常掉電,當(dāng)電力恢復(fù)后,重啟服務(wù)器,發(fā)現(xiàn)網(wǎng)站運(yùn)行出錯(cuò)。在進(jìn)行檢測(cè)時(shí),發(fā)現(xiàn)在讀取表數(shù)據(jù)時(shí)MySQL出現(xiàn)報(bào)錯(cuò)信息。分析其原因,可能是當(dāng)服務(wù)器突然斷電時(shí),數(shù)據(jù)庫(kù)正在向“.MYI”文件中刷新索引信息,造成索引文件結(jié)構(gòu)發(fā)生錯(cuò)誤。實(shí)際上,當(dāng)“.MYI”的頭數(shù)據(jù)損壞(例如第一個(gè)16KB塊等),包含的信息不正確以及該文件丟失等,都會(huì)出現(xiàn)此類(lèi)故障。因?yàn)槭诸^只有“.frm”文件,只有通過(guò)其來(lái)完整恢復(fù)表結(jié)構(gòu),讓表恢復(fù)到可用狀態(tài)。
具體方法是新將“.FRM”文件復(fù)制到數(shù)據(jù)庫(kù)目錄中,針對(duì)“.MYD”和“.MYI”文件,創(chuàng)建對(duì)應(yīng)的空文件。如果存在這些文件,先將其刪除。登錄數(shù)據(jù)庫(kù),執(zhí)行“repair table xxx use_frm”命令,其中的“xxx”為表名,執(zhí)行修復(fù)動(dòng)作,即讓MySQL以該“.frm”文件為基礎(chǔ),來(lái)修復(fù)表文件,來(lái)計(jì)算“.MYD”和“.MYI”文件應(yīng)該具有的內(nèi)容,最后查看恢復(fù)結(jié)果。還以上面的例子進(jìn)行說(shuō)明,假設(shè)只有“sampletb.frm”文件,另外的文件丟失了,當(dāng)執(zhí)行各種查詢命令時(shí),MySQL會(huì)顯示“ERROR 1017(HY000)”的錯(cuò)誤提示。按照上述方法將“sampletb.frm”復(fù)制回來(lái),在Linux命令行下執(zhí)行“touch sampletb.MYD”和“touch sampletb.MYI”命令。來(lái)創(chuàng)建對(duì)應(yīng)的數(shù)據(jù)和索引文件。為了讓MySQL有權(quán)限對(duì)其進(jìn)行處理,執(zhí)行“chown mysql. Sampletb.*”命令,即可實(shí)現(xiàn)該要求。在MySQL命令行中執(zhí)行“repair table sampletb use_frm;”命令,完成后就可以正常操作該表了。
實(shí)際上,可以使用Myisamchk這一專用的工具,對(duì)Myisam表進(jìn)行修復(fù),該命令可以獲取有關(guān)數(shù)據(jù)庫(kù)表的統(tǒng)計(jì)信息,并對(duì)其進(jìn)行檢查,修復(fù)和優(yōu)化。和之前的“repair table”命令不同,該命令可以通過(guò)合理的調(diào)整參數(shù),可以實(shí)現(xiàn)不同的修復(fù)手段和方式,完成細(xì)節(jié)化的調(diào)整。更重要的是,該命令的修復(fù)速度很快,特別是修復(fù)大體積的表時(shí)尤為明顯。
其命令格式為“myisamchk [參 數(shù)]tables[.MYI]”,其 中 的 用來(lái)執(zhí)行檢測(cè)功能的參數(shù)包括“-i”,可以打印所檢查表的統(tǒng)計(jì)信息?!?-F”參數(shù)只檢查有沒(méi)有正確關(guān)閉的表,“-f”參數(shù)用來(lái)執(zhí)行自動(dòng)修復(fù)操作?!?m”參數(shù)可以快速執(zhí)行檢測(cè)操作等。例如,在Linux命令行下執(zhí)行“myisamchk -im /var/lib/mysql/shujuku1/sampletb”命 令,可 以 對(duì)“sampletb”表進(jìn)行快速檢查。執(zhí)行“myisamchk -iFm /var/lib/mysql/shujuku1/*”命令,只檢查未正常關(guān)閉的表。執(zhí)行“myisamchk -eis /var/lib/mysql/shujuku1/sampletb”命令,僅顯示“sampletb”表中最重要信息。
默認(rèn)下,“Myisamchk”命令使用的內(nèi)存過(guò)小,如果要修復(fù)較大的表,速度自然會(huì)很慢,通過(guò)為其設(shè)置更大的內(nèi)存量,可以加速其修復(fù)速度。例如執(zhí)行“myisamchk-sort_buffer_size=32M-key_buffer_size=16M-read_buffer_size=2M-write_buffer_size=2M 具體的修復(fù)參數(shù)等”格式的命令,可以靈活的針對(duì)排序緩沖(用于計(jì)算和建立索引),讀寫(xiě)緩沖等分配指定的內(nèi)存量。在具體進(jìn)行數(shù)據(jù)恢復(fù)時(shí),需要遵循一定的順序。首先應(yīng)該仔細(xì)查看MySQL顯示的錯(cuò)誤碼信息,例如執(zhí)行“myisamchk -im --verbose表名”命令,來(lái)查看具體的錯(cuò)誤碼。
對(duì)于有些簡(jiǎn)單的錯(cuò)誤來(lái)說(shuō),實(shí)際上是無(wú)需進(jìn)行復(fù)雜的修復(fù)操作的。例如對(duì)于Error 135和136錯(cuò)誤來(lái)說(shuō),是因?yàn)橛涗浳募蛩饕募目臻g不夠了,可以在MySQL執(zhí)行“ALTER TABLE sampletb MAX_ROWS=xxx AVG_ROW_LENGTH=xxx”命令,來(lái)擴(kuò)大行所能容納的數(shù)量以及擴(kuò)大索引所能包含的信息,其中的“xxx”為具體的數(shù)字。在執(zhí)行修復(fù)操作時(shí),必須保證“mysqld”服務(wù)沒(méi)有使用到該表,為了穩(wěn)妥起見(jiàn)最高暫時(shí)關(guān)閉該服務(wù)。
如果不關(guān)閉該服務(wù)器的話,要先執(zhí)行“flush tables表名 with read lock”命令將其鎖定,防止兩者同時(shí)對(duì)其訪問(wèn)。否則可能因?yàn)樵摲?wù)和“Myisamchk”命令同時(shí)訪問(wèn)讀寫(xiě)目標(biāo)表,造成其出現(xiàn)損壞的情況。準(zhǔn)備好以上條件后,就可以執(zhí)行具體的修復(fù)動(dòng)作了。
例如,先執(zhí)行“myisamchl-rq sampletb” 命 令,對(duì)“sampletb”表進(jìn)行快速修復(fù)。如果失敗可以執(zhí)行“myisamchl -Br sampletb”命令,來(lái)修復(fù)數(shù)據(jù)本身。如果還失敗,執(zhí)行“myisamchl-o sampletb”命令,進(jìn)行徹底修復(fù)。
其中的“-r”參數(shù)可以修復(fù)幾乎所有的問(wèn)題,“-B”參數(shù)可以將“.MYD”文件備份為指定的文件,備份文件名稱中包含具體的時(shí)間?!?o”參數(shù)表示使用一個(gè)老的恢復(fù)方法按照順序讀取所有行,并根據(jù)找到的行更新所有的索引樹(shù),該參數(shù)的修復(fù)速度是最慢的,其相當(dāng)于對(duì)表進(jìn)行了遍歷?!?q”參數(shù)不修改數(shù)據(jù)文件,僅執(zhí)行快速修復(fù)操作,當(dāng)出現(xiàn)復(fù)制鍵時(shí),可以兩次指定該項(xiàng)以強(qiáng)制“Myisamchk”命令修改原數(shù)據(jù)文件。該參數(shù)可以幫助用戶簡(jiǎn)單的檢查表中數(shù)據(jù)損壞情況(例如索引文件出現(xiàn)問(wèn)題,和表結(jié)構(gòu)有關(guān)的小問(wèn)題等),并實(shí)現(xiàn)快速修復(fù)操作,其并不會(huì)修改“.MYD”文件中存儲(chǔ)的數(shù)據(jù),是一種比較安全的修復(fù)方式,不會(huì)破壞數(shù)據(jù)完整性。
在維護(hù)網(wǎng)站時(shí),筆者有時(shí)會(huì)遇到是某個(gè)數(shù)據(jù)表?yè)p壞,造成數(shù)據(jù)讀寫(xiě)出錯(cuò)的情況,針對(duì)這一情況,完全可以使用“Myisamchk”命令進(jìn)行修復(fù)。還以“sampletb”表為例進(jìn)行說(shuō)明,在MySQL命令行中執(zhí)行“check tables sampletb”命令,系統(tǒng)提示該表數(shù)據(jù)受損。當(dāng)執(zhí)行“flush tables sampletb with read lock;”命令,試圖對(duì)其鎖定,但是系統(tǒng)提示“ERROR 145(HY000)Table is marked as crashed and should be repaired”信息,說(shuō)明其根本無(wú)法讀取,自然不必手工鎖定。返回Linux命令行,執(zhí)行“myisamchk sampletb”命令,對(duì)該表進(jìn)行檢測(cè),根據(jù)返回信息,可以查看具體的錯(cuò)誤信息。執(zhí)行“myisamchk-Br sampletb”命令,就可以將其修復(fù)了。但是,在MySQL中對(duì)其查詢時(shí),可能會(huì)發(fā)現(xiàn)有些數(shù)據(jù)丟失了,這就說(shuō)明在很多情況下,單純依靠修復(fù)操作是無(wú)法找回?cái)?shù)據(jù)的。
此外,當(dāng)索引表丟失后,也可以使用“Myisamchk”命令進(jìn)行有效修復(fù)。例如先將“sampletb.MYD”文件移動(dòng)到別的位置。在Linux命令行下 執(zhí) 行“touch sampletb.MYD” 和“touch sampletb.MYI”命令。來(lái)創(chuàng)建對(duì)應(yīng)的數(shù)據(jù)和索引文件。為了讓MySQL有權(quán)限對(duì)其進(jìn)行處理,執(zhí) 行“chown mysql.Sampletb.*”命令,即可實(shí)現(xiàn)該要求。在MySQL命令行中執(zhí) 行“repair table sampletb use_frm;”命令,修復(fù)索引結(jié)構(gòu)。將“sampletb.MYD”復(fù)制回來(lái),執(zhí) 行“myisamchk -r sampletb” 命 令, 對(duì)“sampletb”表進(jìn)行修復(fù)。