(原文:http://www.mysqlperformanceblog.com/2009/06/16/slow-drop-table/)
衆所周知,EXT3並不是效率最高的文件系統,例如文件刪除就是其隱痛並且會造成大量的隨機I/O。而且,有時會嚴重影響到MySQL的性能。
當我們運行DROP TABLE命令時,會依序發生以下步驟:
1. 給表加寫鎖,以使它不能被其他線程訪問。
2. 存儲引擎(MyISAM,InnoDB...)刪除數據文件
3. MySQL刪除定義文件(.frm)。
但這些並不是全部,期間還有一個步驟:
1. VOID(pthread_mutex_lock(&LOCK_open));
2. error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
3. pthread_mutex_unlock(&LOCK_open);
刪除表的代碼被LOCK_open這個互斥鎖包裹。這個鎖在MySQL的代碼中多次被使用到——主要是打開和關閉表的時候。這表明,當LOCK_open被佔用,所有需要訪問表的查詢都將不能被執行。
在此,EXT3文件系統上緩慢的文件刪除便開始產生影響。刪除10GB的MySQL表要花費幾秒鐘,鎖持續被佔用,以至於全部的查詢都被掛起。
+-----+------+-----------+----+---------+------+----------------+-----------------------------------------------
| Id | User | Host | db | Command | Time | State | Info
+-----+------+-----------+----+---------+------+----------------+-----------------------------------------------
| 1 | root | localhost |test| Query | 7 | NULL | drop table large_table
| 329 | root | localhost |test| Query | 7 | Opening tables | select sql_no_cache * from other_table limit 1
+-----+------+-----------+----+---------+------+----------------+-----------------------------------------------
我曾嘗試過其他方法,試圖讓MySQL刪除小一些的文件以降低影響,例如:
* TRUNCATE TABLE large_table; ALTER TABLE large_table ENGINE=…; DROP TABLE large_table;
* TRUNCATE TABLE large_table; OPTIMIZE TABLE large_table; DROP TABLE large_table;
然而不幸的是,任何管理的指令如ALTER TABLE 或 OPTIMIZE TABLE在刪除舊錶的時候都要使用LOCK_open鎖:
| 3 | root | localhost | test | Query | 7 | rename result table | ALTER TABLE large_table ENGINE=MyISAM
| 679 | root | localhost | test | Query | 6 | Opening tables | select * from other_table limit 1
唯一替換的方法是改變文件系統,例如將文件系統改爲刪除文件更有效的XFS。
EXT3
mysql> drop table large_table;
Query OK, 0 rows affected (7.44 sec)
XFS
mysql> drop table large_table;
Query OK, 0 rows affected (0.29 sec)
更好的解決方法是在MySQL內部模擬刪除表,其實將文件保留並在不使用LOCK_open鎖的情況下物理刪除。然而,實際情況並沒這麼簡單,因爲刪除的指令是由存儲引擎執行的,而並非是MySQL。
以上並非一般情況,但有些時候會引起問題。(例如刪除舊的不用的表)