1. 程式人生 > >讓天下沒有難用的資料庫 » Drop table 出現的問題

讓天下沒有難用的資料庫 » Drop table 出現的問題

由於應用下線,需要把資料庫中相關應用的表刪除,庫中有一千多張表,事先已經將所有的表rename到test庫中,drop table的腳步也已經準備好,所以接下來的工作本以為是很輕鬆的事情,但是在執行指令碼的過程中,發現刪除表的速度感覺有點慢,檢視主機的負載也在挺高的,報警訊息中thread running過高也出現了,發現大多數執行緒的狀態是Opening Tables,但還是勉強的忍受了過去,事後想想為什麼刪除表也會這麼的慢?

在drop table的時候有幾件事情需要去做:

對目標表加上write lock,然後在將資料檔案,資料字典檔案從儲存引擎中刪除,看似簡單的兩個工作,但為什麼會這麼長?下面的程式碼中展示了刪除過程中的工作,在刪除的過程中lock_open mutex會一直用於防止任何query來訪問主表;同時在刪除表資料檔案,資料字典檔案的時候由於檔案系統的原因(ext3)導致大量的隨機i/o,同樣會使得刪除變慢。

VOID(pthread_mutex_lock(&LOCK_open));

error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);

pthread_mutex_unlock(&LOCK_open);

同時在刪除表的過程中,由於innodb_file_per_table=1引數的開啟,每個表有一個數據檔案,而不是共享一個表空間,在drop table的時候,innodb必須檢查LRU連結串列,把該連結串列上屬於該表的page清除,如果該資料庫的buffer pool設定的很大,花費在LRU

搜尋的時間開銷將會很大,同時上千張不同的表開啟,如果table_cache設定不當,則會將table_cache充滿, mysql使用LRU演算法將cache中的表清除,這個時候使得其他查詢很有可能看上去被阻塞了,從而導致了效能上的下降。

同時innodb在開啟每一張表的時候,還需要重新計算每張表的統計資訊,如果有上千張的表,當採用innodb_file_per_table方式管理表的時候,這時候對磁碟i/o,cpu的要求也是很高的,這也是為什麼mysql沒有像oracle一樣需要手動去收集表的的統計資訊,而這個操作是序列的,不能夠並行處理。

綜上所述,drop table的速度受制於檔案系統,lock,cache,LRU等諸多因素;上面一個很重要的因素是innodb_file_per_table=1

引數開啟,導致檔案數量的增多,如果你現在的應用中使用的innodb表是經常需要建立,刪除,那麼將該引數innodb_file_per_table設定為0,使得所有的表共用一個表空間,那麼對效能的提升無疑很明顯的(10倍?)。

參考: