MySQL核心月報2015.03-MySQL·捉蟲動態·pidfile丟失問題分析

db匠發表於2016-05-23

現象

mysql5.5,通過命令show variables like `%pid_file%`; 可以查到pid檔案位置,例如/home/mysql/xx.pid。但發現在此目錄下找不到此pid檔案。


背景知識

mysql pid檔案記錄的是當前mysqld程式的pid。

通過mysqld_safe啟動mysqld時,mysqld_safe會檢查PID檔案,未指定PID檔案時,pid檔案預設名為$DATADIR/`hostname`.pid

  • pid檔案不存在,不做處理
  • 檔案存在,且pid已佔用則報錯”A mysqld process already exists”;檔案存在,但pid未佔用,則刪除pid檔案。

mysqld啟動後會通過create_pid_file函式新建pid檔案,通過getpid()獲取當前程式pid並將pid寫入pid檔案。

因此,通過mysqld_safe啟動時,pid檔案的作用是為了防止同一個資料庫被啟動多次(資料檔案是同一份,但埠不同的情況)。

另一個事實是mysqld在正常關閉時或通過SIGQUIT,SIGKILL,SIGTERM訊號來kill mysqld時,會呼叫clean_up函式將pid檔案刪除。而mysqld異常crash時,pid檔案是保留的。


另外mysqld_safe有一個功能是當mysqld異常crash時,後臺會自動重啟mysqld。mysqld關閉後,mysqld_safe會檢查pid檔案是否存在。如果存在則認為mysqld是異常crash, 需要自動重啟;如果不存在則認為是正常關閉的,不需要自動重啟,mysqld_safe程式也退出。


原因分析


檢視error log發現資料庫在相近的時間內啟動了兩次


前面說到mysqld_safe啟動mysqld時,會根據pid檔案來判斷避免重複啟動mysqld.然而,由於兩次啟動時間較近,導致第一次mysqld啟動生成pid檔案之前,第二個mysqld就已開始啟動了,從而繞過了這個判斷。第一次mysqld啟動會成功,而第二次mysqld啟動會因為檔案鎖而導致啟動失敗。


第二次啟動的mysqld關閉時會將第一次啟動時產生的pid檔案刪除,從而導致pid檔案丟失。

通過mysqld_safe啟動mysqld來重現pid檔案丟失有一定的概率性,必須是同時啟動mysqld_safe。 如果是直接通過mysqld啟動,同時指定相同的引數啟動兩次,那麼就很容易重現了。


修復


參考5.6 官方的修復方法,在上述場景下刪除pid檔案時,需判斷是否是自己新建的pid檔案,同時檔案中的pid是否和自身pid一致,否則不能刪除。參考補丁

MySQL · 答疑釋惑· using filesort VS using temporary

背景

MySQL 執行查詢語句, 對於order by謂詞,可能會使用filesort或者temporary。比如explain一條語句的時候,會看到Extra欄位中可能會出現,using filesort和using temporary。下面我們就來探討下兩個的區別和適用場景。

解釋

1. using filesort

filesort主要用於查詢資料結果集的排序操作,首先MySQL會使用sort_buffer_size大小的記憶體進行排序,如果結果集超過了sort_buffer_size大小,會把這一個排序後的chunk轉移到file上,最後使用多路歸併排序完成所有資料的排序操作。

MySQL filesort有兩種使用模式:

模式1: sort的item儲存了所需要的所有欄位,排序完成後,沒有必要再回表掃描。
模式2: sort的item僅包括<sort_key, rowid>,待排序完成後,根據rowid查詢所需要的columns。

很明顯,模式1能夠極大的減少回表的隨機IO。

2. using temporary

MySQL使用臨時表儲存臨時的結構,以用於後續的處理,MySQL首先建立heap引擎的臨時表,如果臨時的資料過多,超過max_heap_table_size的大小,會自動把臨時錶轉換成MyISAM引擎的表來使用。


從上面的解釋上來看,filesort和temporary的使用場景的區別並不是很明顯,不過,有以下的原則:

filesort只能應用在單個表上,如果有多個表的資料需要排序,那麼MySQL會先使用using temporary儲存臨時資料,然後再在臨時表上使用filesort進行排序,最後輸出結果。


適用場景

我們看一下下面的三個case:




case 1:


case1: order by欄位能夠使用index的有序性,所以沒有使用filesort,也沒有使用temporary。

case 2:


case2: order by謂詞,是在第一個表t1上完成,所以只需要在t1表上使用filesort,然後排序後的結果集join t2表。

case 3:


case 3: order by的欄位在t2表上,所以需要把t1,t2表join的結果儲存到temporary表上,然後對臨時表進行filesort,最後輸出結果。

特別優化

MySQL對order by + limit的filesort做了特別優化,使用Priority queue來儲存結果,即一個堆的結構,只保留top n的資料滿足limit條件。

另外

filesort和temporary都會在tmp目錄下建立檔案,temporary建立的是MYI,MYD檔案。但filesort的檔案, 因為MySQL使用了create->open->unlink->使用->close的方式,隱藏了檔案,以便程式異常結束的時候,臨時檔案能夠自動回收掉,所以在評估tmp目錄空間的時候,需要特別注意。


相關文章