2013-08-07 29 views
11

我逃離我的外殼下面的查詢:MySQL查詢與記錄一大批就會被殺死

mysql -h my-host.net -u myuser -p -e "SELECT component_id, parent_component_id FROM myschema.components comp INNER JOIN my_second_schema.component_parents related_comp ON comp.id = related_comp.component_id ORDER BY component_id;" > /tmp/IT_component_parents.txt 

的查詢運行較長的時間,然後就會被殺死。

但是,如果我添加LIMIT 1000,那麼查詢會一直運行到結束,輸出將寫入文件。

我進一步調查,發現(使用COUNT(*)),這將返回的記錄總數是239553163.

約我的服務器的一些信息是在這裏:

的MySQL 5.5.27

+----------------------------+----------+ 
    | Variable_name    | Value | 
    +----------------------------+----------+ 
    | connect_timeout   | 10  | 
    | delayed_insert_timeout  | 300  | 
    | innodb_lock_wait_timeout | 50  | 
    | innodb_rollback_on_timeout | OFF  | 
    | interactive_timeout  | 28800 | 
    | lock_wait_timeout   | 31536000 | 
    | net_read_timeout   | 30  | 
    | net_write_timeout   | 60  | 
    | slave_net_timeout   | 3600  | 
    | wait_timeout    | 28800 | 
    +----------------------------+----------+ 

這裏的查詢狀態監視我:

copying to tmp table on disk 
    sorting results 
    sending data 
    writing to net 
    sending data 
    writing to net 
    sending data 
    writing to net 
    sending data ... 
    KILLED 

任何猜測這裏有什麼不對?

回答

1

什麼是錯誤的是,你正在返回239 553 163行數據!不要感到驚訝,它需要很多時間來處理。實際上,最長的部分可能會將結果集發送回客戶端。

收回結果集(你真的需要所有這些行嗎?)。或嘗試將數據輸出在小批量:

mysql -h my-host.net -u myuser -p -e "SELECT ... LIMIT 10000, 0" >> dump.txt 
mysql -h my-host.net -u myuser -p -e "SELECT ... LIMIT 10000, 10000" >> dump.txt 
+0

我已經有這樣的想法,把結果集分成小塊。但試圖看看是否有一種解決方法可以一次完成:) 是的,我需要所有的行。這是我試圖完成的任務所要求的。謝謝你的提示。 –

+0

@ManmohanBishnoi您是連接到共享主機,還是您擁有數據庫服務器?在第一種情況下,主持人很可能已經實施了殺死長查詢的東西(我認爲這就是「KILLED」通知的含義)。共享主機可能(希望;)實施這樣的事情,以保護他們的系統再次類似DoS攻擊。 – RandomSeed

+0

這是一個Amazon RDS大型實例。 我已經用類似數量的記錄運行了長查詢INSERT/UPDATE。所以我想我必須向我的DBA詢問這一點。 –

0

你可能想利用OUTFILE mechanizm如果你要傾倒大量的數據。那個或mysql_dump會更有效率(OUTFILE獲得了不鎖定表的好處)。

+0

我有憑證的用戶沒有FILE權限,因此OUTFILE在此處無用。 –

+0

然後,這是與託管服務提供商面對面的問題,因爲這是選擇大批量數據到CSV或其他格式的最佳選擇。 –

1

假設你的意思是8個小時,當你說很長時間時,wait_timeout的值28800導致連接在28,800秒即8小時內下降而沒有進一步的活動。如果您無法優化語句在少於8小時內運行,則應增加此值。

有關wait_timeout變量的更多信息,請參閱this page

interactive_timeout變量用於交互式客戶端的連接,所以如果你從一個交互式會話中運行長查詢,這就是你需要看的一個。

+0

查詢3100秒後死亡。所以我猜這些值是足夠的。 –

+1

隨着RandomSeed的建議,可能會有一個由管理員或作業運行的外部'KILL'命令;定期計劃的事件可能會運行,檢查長時間運行的查詢(如果它總是3100秒,或者它是3100加上或減去180秒或其他類似值,可能是泄漏),運行類似於SELECT id FROM INFORMATION_SCHEMA。 PROCESSLIST WHERE TIME> 3000 AND命令!='Sleep''並殺死它返回的ID –

+0

還有其他查詢需要大約13000秒才能完成,並且它們按預期工作,所以它是一些其他參數/​​變量,我們必須更改得到這個工作。 –

13

mysql客戶端可能耗盡內存。

使用--quick選項不在內存中緩存結果。

0

你在評論中說你的MySQL實例在RDS上。這意味着您無法從同一主機運行查詢,因爲您無法登錄到RDS主機。我想你可能會從本地網絡通過廣域網進行此查詢。

由於網絡緩慢,您很可能會遇到麻煩。你的流程狀態經常顯示「寫入網絡」讓我認爲這是你的瓶頸。

您的瓶頸也可能是排序。您的排序正在寫入臨時表,並且對於結果集來說可能需要很長時間。你可以跳過ORDER BY嗎?

即便如此,即使運行3100秒或更長時間,我也不希望查詢被殺。我想知道你的DBA是否有一些定期的作業會殺死長時間運行的查詢,如pt-kill。詢問你的DBA。

爲了減少網絡傳輸時間,您可以嘗試使用壓縮協議。您可以將--compress-C標誌用於此客戶端(請參閱https://dev.mysql.com/doc/refman/5.7/en/mysql-command-options.html#option_mysql_compress

在緩慢的網絡上,壓縮可以提供幫助。例如,請閱讀以下一些比較:https://www.percona.com/blog/2007/12/20/large-result-sets-vs-compression-protocol/

另一種替代方法是從運行在與您的RDS實例相同的AZ中的EC2現場實例運行查詢。這兩個實例之間的網絡速度會快很多,所以它不會延遲您的數據傳輸。將查詢輸出保存到EC2現貨實例上的文件中。

將查詢結果保存在您的EC2實例中後,您可以使用scp或其他方式將它下載到您的本地計算機,這應該更容忍慢速網絡。

+0

查詢在EC2和RDS之間運行。該查詢需要ORDER BY。但是自從我發佈這個問題以來,很多事情發生了變化。我們有一個運行在PostgreSQL上的完整的新數據庫。 –

+0

啊。我應該更仔細地檢查問題的日期。這在我的Feed中彈出2天前,但它是四年前,你問它。 –