每個 MySQL 版本在發佈前都會在許多平台上進行測試。這並不表示 MySQL 沒有錯誤,但如果有錯誤,應該會非常少而且很難找到。如果您遇到問題,嘗試找出究竟是什麼導致您的系統崩潰總是有幫助的,因為這樣您有更大的機會快速修復問題。
首先,您應該嘗試找出問題是 mysqld 伺服器當機,還是您的問題與您的用戶端有關。您可以執行 mysqladmin version 來檢查您的 mysqld 伺服器已執行多久。如果 mysqld 已當機並重新啟動,您可以透過查看伺服器的錯誤日誌來找出原因。請參閱 第 7.4.2 節,「錯誤日誌」。
在某些系統上,您可以在錯誤日誌中找到 mysqld 當機位置的堆疊追蹤。請注意,寫入錯誤日誌的變數值可能並不總是 100% 正確。
如果您發現 mysqld 在啟動期間的 InnoDB
復原時失敗,請參閱 第 17.20.2 節,「疑難排解復原失敗問題」。
許多非預期的伺服器結束都是由損毀的資料檔案或索引檔案所造成。MySQL 在每個 SQL 陳述式之後,以及在通知用戶端結果之前,都會使用 write()
系統呼叫來更新磁碟上的檔案。(如果您啟用 delay_key_write
系統變數執行,則情況並非如此,在這種情況下,會寫入資料檔案,但不會寫入索引檔案。)這表示即使 mysqld 崩潰,資料檔案內容也是安全的,因為作業系統會確保將未刷新資料寫入磁碟。您可以透過使用 --flush
選項啟動 mysqld,強制 MySQL 在每個 SQL 陳述式之後將所有內容刷新到磁碟。
前面的說明表示,通常除非發生下列情況之一,否則您不應該取得損毀的表格
MySQL 伺服器或伺服器主機在更新期間被強制終止。
您在 mysqld 中找到一個錯誤,導致它在更新期間當機。
某些外部程式在 mysqld 同時操作資料檔案或索引檔案,且未正確鎖定表格。
您正在使用同一個資料目錄在不支援良好檔案系統鎖定(通常由
lockd
鎖定管理員處理)的系統上執行許多 mysqld 伺服器,或者您正在執行多個已停用外部鎖定的伺服器。您有一個當機的資料檔案或索引檔案,其中包含非常損毀的資料,導致 mysqld 混淆。
您在資料儲存程式碼中找到一個錯誤。這不太可能,但至少有可能。在這種情況下,您可以嘗試透過在表格的修復副本上使用
ALTER TABLE
,將儲存引擎變更為另一個引擎。
由於很難知道為什麼會發生當機,請先嘗試檢查對其他人有效的方法是否會導致您的系統出現非預期的結束。嘗試下列事項
使用 mysqladmin shutdown 停止 mysqld 伺服器,從資料目錄執行 myisamchk --silent --force */*.MYI 以檢查所有
MyISAM
表格,並重新啟動 mysqld。這可確保您從乾淨的狀態執行。請參閱 第 7 章,MySQL 伺服器管理。啟用一般查詢日誌啟動 mysqld (請參閱第 7.4.3 節,「一般查詢日誌」)。然後嘗試從寫入日誌的資訊中判斷是否有特定查詢導致伺服器當機。大約 95% 的錯誤都與特定查詢有關。通常,這是伺服器重新啟動之前日誌檔案中的最後一個查詢。請參閱第 7.4.3 節,「一般查詢日誌」。如果您可以使用特定查詢重複導致 MySQL 當機,即使在發出該查詢之前您已檢查過所有資料表,那麼您就已找出錯誤,應提交錯誤報告。請參閱第 1.6 節,「如何回報錯誤或問題」。
嘗試建立一個測試案例,以便我們能重複這個問題。請參閱第 7.9 節,「偵錯 MySQL」。
嘗試
fork_big.pl
指令碼。(它位於原始碼散佈的tests
目錄中。)為偵錯設定 MySQL,如果發生問題,可以更輕鬆地收集有關可能錯誤的資訊。使用
-DWITH_DEBUG=1
選項重新設定 MySQL 的 CMake,然後重新編譯。請參閱第 7.9 節,「偵錯 MySQL」。請確保您已為您的作業系統套用最新的修補程式。
使用
--skip-external-locking
選項啟動 mysqld。在某些系統上,lockd
鎖定管理員無法正常運作;--skip-external-locking
選項會告訴 mysqld 不要使用外部鎖定。(這表示您無法在同一個資料目錄上執行兩個 mysqld 伺服器,如果您使用 myisamchk,則必須小心。儘管如此,嘗試此選項作為測試可能會有所啟發。)如果 mysqld 似乎正在執行但沒有回應,請嘗試 mysqladmin -u root processlist。有時 mysqld 並未真的當機,即使它看起來沒有回應。問題可能在於所有連線都在使用中,或可能存在某些內部鎖定問題。mysqladmin -u root processlist 通常即使在這些情況下也能建立連線,並且可以提供有關目前連線數及其狀態的有用資訊。
執行命令 mysqladmin -i 5 status 或 mysqladmin -i 5 -r status 在另一個視窗中,以便在執行其他查詢時產生統計資料。
嘗試以下步驟
從 gdb (或其他偵錯工具) 啟動 mysqld。請參閱第 7.9 節,「偵錯 MySQL」。
執行您的測試指令碼。
在最低的三個層級印出回溯追蹤和局部變數。在 gdb 中,當 mysqld 在 gdb 內部當機時,您可以使用下列命令執行此動作
backtrace info local up info local up info local
使用 gdb,您也可以使用
info threads
檢查存在哪些執行緒,並使用thread
切換到特定的執行緒,其中N
N
是執行緒 ID。
嘗試使用 Perl 指令碼模擬您的應用程式,強制 MySQL 結束或發生異常。
傳送一般的錯誤報告。請參閱第 1.6 節,「如何回報錯誤或問題」。要比平常更詳細。因為 MySQL 對很多人都有效,所以當機可能是由於僅在您的電腦上存在的問題 (例如,與您特定系統程式庫相關的錯誤) 所導致的。
如果您的資料表包含動態長度列,且您僅使用
VARCHAR
資料行 (而非BLOB
或TEXT
資料行),您可以嘗試使用ALTER TABLE
將所有VARCHAR
變更為CHAR
。這會強制 MySQL 使用固定大小的列。固定大小的列會佔用一些額外的空間,但對損壞的容忍度更高。目前的動態列程式碼已使用多年,幾乎沒有問題,但動態長度列本質上更容易出錯,因此嘗試此策略以查看是否有幫助可能是個好主意。
在診斷問題時,請考慮硬體故障的可能性。有缺陷的硬體可能會導致資料損毀。在疑難排解硬體時,請特別注意您的記憶體和磁碟子系統。