2014-07-23 66 views
3

我注意到如果我使用mysql_query()執行長時間運行的mysql查詢(使用mysql_query()(我知道我不應該使用它),然後PHP進程會被殺死該查詢繼續在mysql服務器上運行。這不是一個持久的連接。連接而成,具有:mysql_query()在php退出後繼續運行

$db = mysql_connect($host, $login, $pass, false); 
$sql = 'SELECT COUNT(*) FROM `huge_table`'; 
$result = mysql_query($sql, $db); 

例如,假設我有1頁十億行的表和PHP程序做到這一點由於某種原因:

SELECT COUNT(*) FROM `huge_table` 

然後超時(說是因爲我運行PHP-FPM與request_terminate_timeout = 5),所以5秒後殺死的過程,以確保它不會養豬的事情。

Eventhough過程中被殺死,查詢仍然在MySQL WAIT_TIMEOUT後運行甚至遠遠。

反正是有保證的是,如果PHP進程退出不管是什麼原因,它也殺死任何正在運行的查詢,它做?

我使用tokudb 38年5月5日 - tokudb-7.1.7-E這是MySQL的38年5月5日

+2

[**在新的代碼,請不要使用'mysql_ *'功能**](HTTP:/ /bit.ly/phpmsql)。他們不再被維護[並且被正式棄用](http://j.mp/XqV7Lp)。請參閱[**紅框**](http:// j。熔點/ Te9zIL)?學習[*準備的語句*](http://j.mp/T9hLWi),並使用[PDO](http://php.net/pdo)或[MySQLi](http://php.net/ mysqli) - [這篇文章](http://j.mp/QEx8IB)將幫助你決定哪個。如果你選擇PDO,[這裏是一個很好的教程](http://j.mp/PoWehJ)。 – esqew

+0

要添加上述評論,較新的客戶端庫(如PDO和* mysqli *)可能更好地處理退出過程。我至少會用* mysqli *重試你的嘗試,看看它是否有所作爲。 – Phil

+2

我知道。這是舊代碼。我重新使用mysqli來運行一個測試,它具有相同的行爲,所以我不認爲它與使用mysql_query而不是mysqli_query – crickeys

回答

3

crickeys,當PHP腳本開始執行,它到達的地方執行MySQL查詢的一部分,該查詢是手到MySQL。查詢的控制不再在PHP的手中...... PHP在這一點上只是等待MySQL的響應,然後才能繼續。殺死PHP腳本不影響MySQL查詢,因爲很好,查詢是MySQL的業務。換句話說,PHP走到門口,敲門,交出貨物,等待你帶回一個響應,以便他可以在途中。射擊他不會影響到門後發生的事情。

您可以運行這樣的事情來檢索最長正在運行的進程,並殺死他們:

<?php 
    $con=mysqli_connect("example.com","peter","pass","my_db"); 
// Check connection 
if (mysqli_connect_errno()) { 
    echo "Failed to connect to MySQL: " . mysqli_connect_error(); 
} 

$result = mysqli_query($con,"SHOW FULL PROCESSLIST"); 

while($row = mysqli_fetch_array($result)) { 
if ($row["Time"] > $max_excution_time) { 
    $sql="KILL ".$row["Id"]; 
    mysql_query($sql); 
    } 

} 

mysqli_close($con); ?> 
+0

但腳本結束時php不關閉任何連接到MySQL數據庫?如果是這樣,如果與它的連接關閉,mysql是否不取消查詢? – crickeys

+0

不,PHP不會關閉連接,因爲它們不在手中了。一個連接只有在PHP返回時才能關閉,即當MySQL返回結果時。在發送查詢和接收結果之間,MySQL是老闆。 mysqli_close($ connection)在檢索結果後運行;在此之前,您需要管理MySQL級別的連接。 – kakoma

+1

其實,是的,PHP或OS會在連接不再運行時「關閉」連接,因爲沒有運行的連接不能有開放的連接......但這並不重要,因爲MySQL不會知道或關心PHP在下一次嘗試將*寫入關閉的連接時所做的事情。當發生這種情況時,連接將完全重置,並且MySQL的客戶端線程將從流程列表中消失。雖然稍微不準確,但這個答案確實解釋了問題的高層次性質。 –

0

那麼你可以使用一個析構函數調用

mysql_close();功能。 我希望我理解你的問題......

+0

即使我把它放在一個register_shutdown事件中,它調用了原始數據庫連接上的mysql_close,它仍然在mysql上運行。 – crickeys

0

您可以使用KILL

  • KILL CONNECTION相同KILL無改性劑:它終止與所述給定的thread_id關聯的連接。
  • KILL QUERY終止該連接當前執行的語句,但離開連接本身完好無損。

你應該KILL QUERY在關機的情況下,然後做一個mysqli_close()


你可能會得到來自這個問題有關超時的一些有價值的信息:Client times out, while MySQL query remains running?

+0

我試着在register_shutdown中看到數據庫連接已經消失了,因爲它給出了:「MySQL服務器已經消失」。不知道這是什麼意思,如果這表示MySQL或PHP的問題。 – crickeys

+0

然後我想你必須用一個單獨的過程來完成'KILL'。希望[這](http://dba.stackexchange.com/a/2637)可以幫助你。 – Krumia