原文:http://t.dbdao.com/archives/mysql%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AE%A1%E7%90%86-%E8%A1%A8%E7%9A%84%E7%BB%B4%E6%8A%A4.html
一、目標
完成本課程后,你應該能夠:
- 認識不同類型的表維護操作
- 執行維護表的SQL語句
- 使用客戶端和實用程序維護表
- 根據具體的存儲引擎維護表
二、實施表的維護
- 表的維護操作對識別和解決數據庫問題非常有用,例如:
- 因服務器崩潰而損壞的表
- 表上查詢處理緩慢
- 許多工具可以執行表的維護
- MySQL Workbench(MySQL工作台)
- MySQL Enterprise Monitor(MySQL企業版監視器)
- SQL(DML)Maintenance statements(SQL <DML>維護語句)
- 工具:
- mysqlcheck
- Myisamchk
- Server auto-recovery(服務器自動恢復)
三、使用SQL進行表的維護操作
- 有多條SQL語句可以執行表的維護:
- ANALYZE TABLE : 更新索引的統計信息
- CHECK TABLE : 檢查表的完整性
- CHECKSUM TABLE : 報告表數據的一致性檢測結果
- REPAIR TABLE : 修復表
- OPTIMIZE TABLE : 優化表
- 每條語句需要一個或多個表名和可選關鍵字。
- 一條維護語句和輸出的樣例:
備注:
在執行請求的操作之后,服務器返回操作的結果信息到客戶端。
結果信息以四列格式顯示:
- Table : 標示執行操作的表
- Op : 操作的名字(check,repair,analyze,或optimize)
- Msg_type : 提供一個成功或失敗的指示器
- Msg_text : 提供額外的信息
如果想獲取關於MySQL表維護的更多信息,可以參照文檔:
MySQL Reference Manual
http://dev.mysql.com/doc/mysql/en/table-maintenance-sql.html
一、ANALYZE TABLE(分析表)語句
- 分析並存儲表的鍵值分布統計信息
- 為執行查詢提供更好的選擇
- 對使用InnoDB,NDB和MyISAM存儲引擎的表生效
- 支持分區表
- ANALYZE TABLE選項:
- NO_WRITE_TO_BINLOG或LOCAL : 不記錄二進制日志
- 一條ANALYZE TABLE語句結果的樣例:
備注:
當你執行一個除常數之外的連接時,MySQL使用存儲的鍵值分布統計信息決定如何優化表連接的順序。另外,鍵值分布決定了查詢中具體的表MySQL使用什么索引。
你可以執行ANALYZE TABLE語句分析和存儲統計信息,或者你可以配置InnoDB,在數據變化后或者你查詢表或索引的元數據時,將會自動收集統計信息。
ANALYZE TABLE 的特點:
- 在分析過程中,MySQL在使用InnoDB和MyISAM引擎的表上加上一個只讀鎖
- 這條語句等價於使用mysql check –analyze語句
- 需要有表的SELECT和INSERT權限
- 支持分區表。你也可以使用ALTER TABLE …ANALYZE PARTITION來檢查一個或多個分區。
如果表自從上次執行ANALYZE TABLE語句后沒有發生過改變,MySQL將不分析該表。
默認情況下,MySQL將ANALYZE TABLE語句寫入二進制日志並且將其復制到從庫。
使用可選的關鍵字NO_WRITE_TO_BINLOG或它的別名LOCAL來設置不記錄日志。
續:備注:
你可以使用以下選項控制MySQL如何收集和存儲鍵值分布統計信息:
- innodb_stats_persistent :
當該選項設置為ON,MySQL將在新建的表上啟用STATS_PERSISTENT設置。你也可以在使用CREATE TABLE 或者 ALTER TABLE 語句時使用STATS_PERSISTENT。
默認情況下,MySQL不會持續將鍵值分布的統計信息寫入磁盤,所以它們(統計信息)必須在某些時間(重新)生成,比如服務器重啟。當(對某些表)啟用STATS_PERSISTENT時,MySQL將存儲這些表的鍵值分布統計信息至磁盤,這樣這些表將不需要再頻繁生成統計信息。這使得隨着時間的推移,優化器可以創建更一致(穩定)的查詢計划。
- innodb_stats_persistent_sample_pages :
MySQL通過對STATS_PERSISTENT表的索引頁采樣而非整張表重新生成統計信息。
默認情況下,它對樣例的20頁進行采樣,增加頁數可以提升生成的統計信息的准確性和生成更精准的查詢計划。
減少頁數可以減少生成統計信息時I/O的消耗。
- innodb_stats_transient_sample_pages :
當STATS_PERSISTENT未設置的時候,該選項控制表上索引頁的采樣數量。
以下選項控制MySQL如何自動收集統計信息。
- innodb_stats_auto_recalc :
啟用該選項時,當STATS_PERSISTENT表自上次重新統計后,有10%行記錄改變時,MySQL將自動收集統計信息。
- innodb_stats_on_metadata :
當你執行SHOW TABLE STATUS或其他元數據語句?,或當你查詢INFOMATION_SCHEMA.TABLES時,啟用該選項將更新統計信息。
默認情況下,該選項是禁用的。
一、CHECK TABLE(檢查表)語句
- 檢查表結構和內容的完整性
- 驗證視圖定義
- 支持分區表
- 對使用InnoDB,CSV,MyISAM和ARCHIVE(存儲引擎)的表生效
- CHECK TABLE選項:
- FOR UPGRADE : 檢查當前服務器的表是否工作?
- QUICK : 不掃描不正確鏈接的行
- 如果CHECK TABLE發現使用InnoDB存儲引擎的表有錯誤:
- 服務器將會被關閉以防止錯誤傳播
- MySQL將會記錄錯誤到錯誤日志
備注:
CHECK TABLE特點:
- 對於使用MyISAM存儲引擎的表,鍵值統計信息也會被更新。
- 也可以檢查視圖的問題,例如表中引用的視圖定義並不存在。
- 支持分區表。你也可以使用ALTER TABLE…CHECK PARTITION來檢查一個或多個分區。
對於FOR UPGRADE子句,服務器檢查每個表以確認表結構是否與當前版本的MySQL兼容。數據類型的存儲格式更改或者它的排序順序改變都可能導致不兼容。如果這里可能存在不兼容,服務器將在表上運行一個完整的檢查,如果完整檢查成功,服務器將會在表的.frm文件上標記當前MySQL版本的數字。標記.frm文件可以確保該表未來做(與文件標記)同樣版本服務器檢查時快速檢查。
在InnoDB,MyISAM和ARCHIVE存儲引擎上可使用FOR UPGRADE。
使用InnoDB和MyISAM存儲引擎的表上可使用QUICK。MyISAM支持更多選項。
查閱http://dev.mysql.com/doc/mysql/en/check-table.html可獲得更多信息。
續:五、CHECK TABLE(檢查表)語句
- 一個好的CHECK TABLE結果樣例:
備注:
如果CHECK TABLE的輸出表明表有問題,修復該表。
例如,你可以在修復表之前使用CHECK TABLE語句檢測硬件問題(例如內存錯誤或磁盤扇區損壞)。Msg_text輸出列正常顯示為“OK”。如果得到的(結果)不是“OK”或“Table is already up to date”,對表執行修復。
如果表被標記為“corrupted”或“not closed properly”,但CHECK TABLE沒有在表上發現任何錯誤,將會標記表為“OK”。
一、CHECKSUM TABLE(校驗表)語句
- 報告表的checksum
- (該語句)用來驗證表備份,回滾或者其他操作之前或之后內容是否一致
- 讀取整個表逐行進行校驗
- 默認選項EXTENDED提供這種行為
- QUICK選項在MyISAM表上可用。
- MyISAM 上默認選項為設置CHECKSUM=1。
- 一條CHECKSUM TABLE語句的樣例:
備注:
CHECKSUM TABLE特點:
- CHECKSUM TABLE需要SELECT表的權限
- 對於不存在的表,CHECKSUM TABLE返回“NULL”並且生成一條警告
- 如果使用了EXTENDED選項,逐行讀取整張表,並且計算checksum的值。
- 如果使用QUICK選項:
- 如果表的在線checksum可用將會給出報告,否則報告(顯示)為“NULL”,這操作將會很快速。
- 你創建表時為MyISAM表指定CHECKSUM=1將會啟用在線checksum。
- 如果既沒有指定QUICK又沒有指定EXTENDED,MySQL設置選項為EXTENDED,除非MyISAM表CHECKSUM=1。
checksum的值取決於表的行記錄的格式,如果行記錄的格式改變,checksum也會改變。
比如,“VARCHAR”存儲類型在MySQL4.1之后發生了改變,所以如果你升級一張4.1版本的表到更新的版本,包含VARCHAR列的表的checksum值將會改變。
續:備注:
注意:
如果兩張表的checksums值不同,這可能說明它們可能在某些方面不同。
自從CHECKSUM TABLE使用哈希函數后,不能保證沒有沖突,這將會有極小的可能導致兩張不同的表得到相同的checksum值。
一、OPTIMIZE TABLE(優化表)語句
- 整理表的碎片
- 重建表和釋放未使用的空間以整理碎片
- 優化過程中會鎖定表
- 更新索引統計信息
- 在一張永久的,數據密集/完全填充?的表上是比較好的
- 在InnoDB,MyISAM和ARCHIVE表上生效
- 支持分區表
- OPTIMIZE TABLE選項:
- NO_WRITE_TO_BINLOG或LOCAL:不記錄二進制日志
備注:
OPTIMIZE TABLE特點:
- 對刪除、更新和接合記錄等引起的分散的,非連續的數據中涉及到的未使用的可回收空間進行碎片整理
- 需要表的SELECT和INSERT權限
- 支持分區表。你可以使用ALTER TABLE…OPTIMIZE PARTITION檢查一個或多個分區。
例如,你可以在表的行記錄數發生大幅度修改后,使用OPTIMIZE TABLE語句在InnoDB中重建一個FULLTEXT(全文)索引。
在InnoDB表中,OPTIMIZE TABLE和ALTER TABLE類似,將重建表以更新索引統計信息和群集索引中空閑的未使用的空間?
InnoDB和其他存儲引擎產生碎片的方式不同,所以你不需要經常(在InnoDB上)使用OPTIMIZE TABLE。
在ARCHIVE存儲引擎上使用OPTIMIZE TABLE可以壓縮表。
使用SHOW TABLE STATUS語句查看ARCHIVE表行數產生的結果往往比較准確。在執行優化操作時會產生一個.ARN文件。
續:七、OPTIMIZE TABLE(優化表)語句
以下OPTIMIZE TABLE語句優化了兩張mysql數據庫中數據密集/完全填充?的表:
備注:
對於MyISAM表,在對表的大部分數據刪除或者在可變長度行記錄(包含VARCHAR,VARBINARY,BLOB或TEXT列)做出修改后,使用OPTIMIZE TABLE語句。
被刪除的行都保存在一個鏈接列表中,並且隨后的INSERT(插入)操作重復使用舊的行的位置。
OPTIMIZE TABLE在完全填充且數據很少改變的表上有較好的優化小故宮。當數據變化比較多時優化效果變差,並且你不得不經常進行優化。
一、REPAIR TABLE(修復表)語句
- 修復可能已經損壞的MyISAM或ARCHIVE表
- 不支持InnoDB
- 優化過程中會鎖定表
- 支持分區表
- REPAIR TABLE選項:
- QUICK : 僅僅修復索引樹
- EXTENDED : 逐行創建索引(替代以排序方式一次創建一個索引)
- USE_FRM : 使用.FRM文件重新創建 .MYI 文件
- NO_WRITE_TO_BINLOG或LOCAL:不記錄二進制日志
備注:
REPAIR TABLE特點:
- QUICK 選項:
僅僅嘗試對索引而非數據文件進行修復。這個修復選項和myisamchk –recover –quick 接近。
- EXTENDED選項:
MySQL逐行創建索引而非以排序方式一次創建一個索引。這種類型修復與myisamchk –safe-recover接近。
- USE_FRM選項不能在分區表上使用。
- 需要表上的SELECT和INSERT權限。
- 支持分區表。你可以使用ALTER TABLE…REPAIR PARTITION來檢查一個或多個分區。
最好在隊標執行修復操作之前對表進行備份,在某些情況下,該操作可能會導致數據丟失。可能會引起(但是不限於)數據文件錯誤。
如果在執行REPAIR TABLE操作期間服務器崩潰,你必須在服務器重啟之后執行其他任何操作之前再次執行REPAIR TABLE指令來避免進一步的錯誤。
如果你需要頻繁的執行REPAIR TABLE語句來修復某張故障表,嘗試去找出底層原因來預防類似錯誤並且消除使用REPAIR TABLE的需求。
續:八、REPAIR TABLE(修復表)語句
- 一個REPAIR TABLE語句樣例:
一、mysqlcheck客戶端程序
- mysqlcheck是一條檢查,修復,分析和優化表的客戶端命令行
- 可以更方便的執行一條SQL語句
- 對InnoDB,MyISAM和ARCHIVE存儲引擎的表生效
- 三個檢查級別:
- 指定表
- 指定數據庫
- 指定所有數據庫
- 一些mysqlcheck維護選項:
- –analyze : 執行一條ANALYZE TABLE語句
- –check : 執行一條CHECK TABLE語句(該選項為默認選項)
- –optimize : 執行一條OPTIMIZE TABLE語句
- –repair : 執行一條REPAIR TABLE語句
備注:
在某些情況下,mysqlcheck可以更方便直接地執行SQL語句。
例如日,如果你將數據庫名作為參數,mysqlcheck會對該數據庫中包含的所有表和問題語句都進行處理?你不需要提供明確的表名作為參數。
同樣的,由於mysqlcheck是一個命令行程序,你可以方便地使用它在操作系統作業上執行計划管理。
續:九、mysqlcheck客戶端程序
- Oracle建議(為什么不是Mysql建議⊙﹏⊙)先不加選項執行myqlcheck命令。如果需要修復再次執行它。
- 一些mysqlcheck限制選項:
- –repair –quick : 嘗試執行一次快速修復
- –repair : 常規修復(如果快速修復失敗)
- –repair –force : 強制執行一次修復
- mysqlcheck樣例:
備注:
默認情況下,mysqlcheck將第一個非選項參數解讀為數據庫名,並且檢查數據庫中所有表。如果在數據庫名參數后有其他參數,將被作為表名,並且僅僅檢查這些表。
上圖展示的mysqlcheck 樣例說明了以下內容:
- 第一條帶選項的指令僅僅檢查world_innodb數據庫中的City和Country表。
- 帶有–database(或 -B)選項的樣例中,mysqlcheck會將該參數作為數據庫名,並且檢查名為world_innodb和test數據庫中的表。
- 帶有–all-database(或 -A)選項時,mysqlcheck檢查所有數據庫中的所有表。
一、myisamchk 工具
- myisamchk 是一個檢查MyISAM引擎表的非客戶端實用工具
- myisamchk 和mysqlcheck工具有以下差異:
- 它可以啟用和禁用索引
- 它可以不通過服務器直接訪問表文件
- 這避免了並發表查詢
- 一些myisamchk 的選項:
- –recover : 修復一張表
- –safe-recover : 修復一張不能使用–recover選項修復的表?
- myisamchk樣例:
備注:
從概念上看,myisamchk和mysqlcheck在功能上很相似。然而,myisamchk並不和MySQL服務器通信。相反的,它直接從文件訪問表。
在執行表維護時使用myisamchk可以避免表的並發訪問:
- 確保在服務器工作時不能訪問表。保障的方法是鎖定表或者停止服務器。
- 在命令提示符中,將當前目錄更改為數據庫中存放表的路徑。 這是具有和數據庫包含的將要被檢查的表有同樣名字的服務器的數據目錄的子目錄?(切換目錄的原因是可以更方便的查看表文件)
- 使用選項調用myismchk指明將要執行的操作,跟在myismchk指令后的參數指定將要被操作的表名。每個參數都可以是表名或表上索引文件的名字。索引文件名和表名一致,並添加.MYI后綴。因此,一張表可以被寫作table_name(表名)或MYI(該表的索引文件名)。
- 重啟服務器。
注意:
先使用–recover,inwei–safe-recover會慢許多。
一、mysqlcheck和myisamchk的選項
控制維護執行類型的選項:
備注:
myisamchk和mysqlcheck都有多個控制表維護操作類型的選項。
上圖的表中列舉了一些常用的選項,其中大部分可以在兩個程序(mysqlcheck和myisamchk)中使用。除了這種情況外,(其余情況)將在相關選項說明中指出。?
- –analyze :
分析表中鍵值分布。這可以提高基於索引查找的查詢語句速度的性能。
- –auto-repair :
如果檢查操作發現問題,自動修復表。
- –check 或 -c :
檢查表的問題。當沒有指定其他選項時,該選項為默認動作。
- –check-only-changed 或 -c :
跳過表查詢,除非表自從上次檢查后發生了改變或者沒有正確關閉。后者可能在表打開時服務器崩潰的情況下發生。
- –fast 或 -F :
跳過表檢查除非表沒有被正確關閉。
- –extended,–extend-check,或 -e :
運行擴展的表檢查。
對於mysqlcheck,當該選項和repair(修復)選項一起使用時,將會比單獨使用repair (修復)選項時進行更全面徹底的修復。就是說,使用–repair –extended選項比使用 –repair選項執行更徹底的修復操作。
續:十一、mysqlcheck和myisamchk的選項
- –extended,–extend-check,或 -e :
運行中級表檢查
- –quick或-q :
對mysqlcheck指令,使用–quick選項不使用repair(修復)選項,僅僅只有索引文件被檢查,而不檢查數據文件。對於兩個程序(mysqlcheck和myisamchk),使用–quick選項和repair(修復)選項,僅僅只有索引文件被檢查,而不檢查數據文件。
- –repair,–recover,或 -r :
運行一個表修復操作。
一、InnoDB表維護
- InnoDB引擎表在故障發生后自動修復
- 使用CHECK TABLE或者一個客戶端程序找出不一致、不兼容和其他問題。
- 使用mysqldump語句通過導出還原一張表:
- 然后刪除它並且從導出的文件重新創建表。
- 為了在(服務器)崩潰后恢復表,使用–innodb_force_recovery選項啟動服務器,或者從一個備份復原表。
- 使用ALTER TABLE重建表和釋放在群集索引中未使用的空間以進行優化
備注:
如果表檢查顯示有問題,使用mysqldump指令通過導出還原表到一致性狀態,刪除它,然后再從導出的文件重建表。
萬一發生數據庫運行的主機或者服務器崩潰,使用InnoDB存儲引擎的表可能額處於不一致的狀態。作為(服務器)啟動的一個步驟,InnoDB存儲引擎將執行自動恢復。
極少見的情況下,可能服務器由於錯誤的自動恢復不能啟動。如果遇到這樣的情況,可以嘗試以下的過程:
- 重啟服務器時,將–innodb_force_recovery選項值設置為1 – 6。
這個值表明避免崩潰警告的增進級別和恢復表時寬限表可能不一致的增進級別。
建議值從4開始,可以防止insert buffer(插入緩沖區)合並操作發生。
- 當服務器以參數–innodb_force_recovery選項設置為非零值啟動時,InnoDB阻止INSERT,UPDATE或DELETE操作。因此,當該選項生效時你需要導出InnoDB表,然后刪除表。然后,再去掉–innodb_force_recovery選項啟動服務器,當服務器啟動后,從導出的文件恢復表。
- 如果前面描述的步驟都失敗了,從以前的備份還原表。
查閱http://dev.mysql.com/doc/mysql/en/forcing-innodb-recovery.html可以獲得更多從崩潰的數據庫啟動InnoDB的信息。
一、MyISAM表維護
- 使用CHECK TABLE…MEDIUM(該選項為默認選項)
- 使用客戶端程序運行myisamchk:
- 表損壞使用通常發生在索引中,標記這些檢查將會很有用。
- 當表損壞時,該工具修復表。
- 設置服務器運行檢查並且自動修復表。
- 使用 –myisam-recover選項啟用自動修復
- 服務器在啟動后第一次訪問是檢查每一張MyISAM表,以確保上一次是正常關閉。
- 根據“config”文件強制恢復MyISAM表。
備注:
默認的CHECK TABLE(檢查表)檢查類型是為動態與靜態格式的表執行MEDIUM(中級)檢查。
如果一個靜態格式表類型設置為CHANGED或FAST,則默認值為QUICK。
對於CHANGED和FAST值將會跳過行掃描,因為這些行很少會出現損壞。
如果表被標記為“corrupted”或“not closed ”,CHECK TABLE將修改表。
如果沒有發現表上有任何問題,將會被標記為“up to date”。
如果表有損壞,問題多數出現在索引而不是數據上。
選項 –myisam-recover可以包含以下一個或多個以逗號分割的列表:
- DEFAULT : 默認檢查
- BACKUP : 告訴服務器對必須改變的表進行備份
- FORCE : 即使丟失超過一行數據,仍然執行表恢復
- QUICK :
執行一次快速恢復。恢復跳過刪除或更新的行沒有間隔(known as“holes”?)的表。
續:備注:
例如,告知服務器對發現有問題的MyISAM表進行強制恢復,但要對表改變的部分做一個備份,添加以下內容到你的選項文件:
[mysqld]
Myisam-recover=FORCE,BACKUP
一、內存表維護
- 當使用一條..WHERE語句刪除行記錄時,MEMORY(內存)表不釋放內存。
- 為了釋放內存,你必須執行一條空ALTER TABLE操作。
- 為了查看MEMORY(內存)表的存儲要求,執行SHOW TABLE STATUS並且添加Data_length和Index_length列。
- 如果刪除行沒有重復值,Data_free列為非零。
備注:
以下是一條SHOW TABLE STATUS語句在world_innodb數據庫City表副本CityCopy表上執行的輸出結果。
CityCopy表使用MEMORY存儲引擎:
mysql> SHOW TABLE STATUS LIKE ‘CityCopy’\G
*************************** 1. row ***************************
Name: CityCopy
Engine: MEMORY
Version: 10
Row_format: Fixed
Rows: 4079
Avg_row_length: 67
Data_length: 383072
Max_data_length: 10808373
Index_length: 253984
Data_free: 0
…:
1 row in set (0.00 sec)
The total memory the CityCopy table occupies can be calculated as follows:
Data_length (383072) + Index_length (253984) = 637056 bytes
二、ARCHIVE表維護
- ARCHIVE壓縮問題:
- 數據插入時表的行記錄被壓縮。
- 進行檢索時?,行記錄可以根據需要不壓縮、
- 一些SELECT語句可能導致壓縮惡化?
- 使用OPTIMIZE TABLE或REPAIR TABLE可以實現更好的壓縮。
- OPTIMIZE TABLE在表沒有被訪問(讀或寫)時生效。
三、總結
在本課程中,你已經學習到如何:
- 認識表維護操作的類型
- 執行SQL語句維護表
- 使用客戶端和工具程序維護表
- 根據具體的存儲引擎維護表
實踐13-1概覽:
測驗 – 維護表
在本測驗中,你需要回答關於MySQL表維護的問題。
實踐13-2概覽:
使用維護表的SQL語句
在本測驗中,你使用SQL語句檢查和優化表。
實踐13-3概覽:
使用表維護工具
在本測驗中,你使用MySQL命令行工具檢查並修復一張表。








