2013-02-15 112 views
3
<?php 
header('Content-Type: text/html; charset=utf8'); 
$dbhost = '192.168.1.23'; 
$dbuser = 'demouser01'; 
$dbpass = 'demo*PW'; 
$dbname = 'testdb1'; 
$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die('Error with MySQL connection'); 
mysql_select_db($dbname); 
mysql_query("SET NAMES 'utf8'"); 
mysql_query("SET CHARACTER_SET_CLIENT='utf8'"); 
mysql_query("SET CHARACTER_SET_RESULTS='utf8'"); 
if(isset($_POST['start'])) { 
    $chi = 'chiiiii'; 
    $id = 1; 
    for ($i = 1; $i <= 99999999999; $i++) { 
    $eng = substr(str_shuffle(str_repeat("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 5)), 0, 1024); 
    $math = substr(str_shuffle(str_repeat("1234567890", 6)), 0, 16); 
    $sql = "INSERT INTO test_tb (id,chi,eng,num) VALUES (".$id.",'".$chi."','".$eng."',".$math.")"; 
    $result = mysql_query($sql) or die('MySQL query error'); 
    $id++; 
    } 
    $id = 0; 
    sleep(60); 
    mysql_close($conn); 
} else if(isset($_POST['stop'])) { 
    mysql_close($conn); 
} 
?> 
<form action="<?=$_SERVER['PHP_SELF'];?>" method="post"> 
    <input type="submit" name="start" value="Start Insert"> 
    <input type="submit" name="stop" value="Stop Insert"> 
</form> 

網站上有兩個按鈕,插入可反覆插入記錄,並停止暫停插入。但是,我嘗試使用MySQL關閉連接,它將停止在PHP中運行,但活動仍然存在。插入仍然繼續執行。如何解決這個問題?謝謝。MYSQL關閉連接無法暫停插入活動

+1

[**請不要在新代碼中使用'mysql_ *'函數**](http://bit.ly/phpmsql)。他們不再被維護[並被正式棄用](https://wiki.php.net/rfc/mysql_deprecation)。看到[**紅框**](http://j.mp/Te9zIL)?學習[*準備的語句*](http://j.mp/T9hLWi),並使用[PDO](http://php.net/pdo)或[MySQLi](http://php.net/ mysqli) - [這篇文章](http://j.mp/QEx8IB)將幫助你決定哪個。如果你選擇PDO,[這裏是一個很好的教程](http://j.mp/PoWehJ)。 – h2ooooooo 2013-02-15 10:39:17

+0

..說,你爲什麼試圖插入'99,999,999,999'記錄到數據庫中?你的主要問題是,在stop命令中引用的'conn'與在另一個命令中啓動的$ conn'不同,因爲它們是兩個不同的請求。你**可以**將句柄('$ conn')保存在一個'$ _SESSION'變量中,然後引用它。 – h2ooooooo 2013-02-15 10:40:17

+0

PDO對我的情況有任何功能?感謝您的幫助 – user782104 2013-02-15 10:41:03

回答

2

由於PHP不允許你分享requestes之間的資源(據我所知),有可以實現這種能力停止在另一個請求處理的幾種方法:

第一添加此行:

if (isset ($_POST['start'])) { 
    $_SESSION['continue'] = true; 

,然後替換你與while語句(好像你不關心itterations的數量,如果是的話你可以恰克這種行爲):

for ($i = 1; $i <= 99999999999; $i++) { 

替換爲:

while ($_SESSION['continue']) 

和,而不是關閉連接停止插入這樣做:

mysql_close ($con) 

將chnage到:

$_SESSION['continue'] = false; 

注意:不要忘記在腳本開始時調用session_start()。 這就是全部。

我假設你想停止來自同一會話的頁面,如果不是這種情況,你可以使用ACP或SHM代替。例如:

取代:

$_SESSION['continue'] = true 

與:

apc_store('continue', true); 

while ($_SESSION['continue']) 

與:

while (acp_fetch ('continue')) 

$_SESSION['continue'] = false; 

有:

apc_store('continue', false); 

完成!

+2

會話將無法工作,除非您想在工作者腳本的每個循環迭代中打開和關閉會話文件(如果這甚至可能) – 2013-02-15 13:04:24

+0

@fab,是的,你是對的!謝謝。我只是錯過了那個帖子。所以最好的方法是使用APC或SHM。 – Boynux 2013-02-15 20:42:10

+0

@Boynux及後來的讀者。我覺得最好,最簡單的方法是使用數據庫。 – regilero 2013-03-01 17:44:44

1

每次調用PHP腳本都會打開自己與MySQL的連接,它們不會互相干擾。連接打開的連接例外是mysql_pconnect():它們保持打開狀態並且將被共享,但是也可以使用mysql_close()關閉而不是

結論:你試圖做的事情是行不通的(反正也是一個壞主意)。

你可能想要的是爲你的插入創建一個後臺任務並檢查那裏的中斷消息(這可能像一個空文件.STOP[PID][PID] =進程ID一樣簡單)。

UPDATE:

Can I not to use APC ?

是的,你可以使用 APC此消息,前提是APC擴展安裝。這不是這種情況,因此,此錯誤:

Call to undefined function acp_fetch() in /home/ext/library/public/testdb/test.php on line 31

您是否具有對服務器的根訪問權限?然後,你可以自己安裝的擴展:

sudo pecl install apc 

如果此命令不起作用,則需要首先得到PECL安裝程序,在這裏看到:sudo pecl install apc returns error

1

這裏是一個完整的解決方案:

<?php 
    header('Content-Type: text/html; charset=utf8'); 

    $dbhost = '192.168.1.23'; 
    $dbuser = 'demouser01'; 
    $dbpass = 'demo*PW'; 
    $dbname = 'testdb1'; 

    $SHMKEY = ftok (__FILE__, 'a'); 
    $SHMID = shm_attach ($SHMKEY); 

    if (!shm_has_var ($SHMID, 1)) { 
     shm_put_var ($SHMID, 1, true); 
    } 

    $conn = mysql_connect($dbhost, $dbuser, $dbpass) or die('Error with MySQL connection'); 
    mysql_select_db($dbname); 

    mysql_query("SET NAMES 'utf8'"); 
    mysql_query("SET CHARACTER_SET_CLIENT='utf8'"); 
    mysql_query("SET CHARACTER_SET_RESULTS='utf8'"); 

    if(isset($_POST['start'])) { 
     $chi = 'chiiiii'; 

     $id = 1; 

     // for ($i = 1; $i <= 99999999999; $i++) { 
     while (shm_get_var ($SHMID, 1)) { 

     $eng = substr(str_shuffle(str_repeat("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 5)), 0, 1024); 

     $math = substr(str_shuffle(str_repeat("1234567890", 6)), 0, 16); 
     $sql = "INSERT INTO test_tb (id,chi,eng,num) VALUES (".$id.",'".$chi."','".$eng."',".$math.")"; 
     $result = mysql_query($sql) or die('MySQL query error'); 
     $id++; 
     } 

     $id = 0; 
     shm_detach ($SHMID); 
     sleep(60); 

     mysql_close($conn); 
    } 

    else if(isset($_POST['stop'])) { 
    shm_put_var ($SHMID, 1, false); 
    // mysql_close($conn); 
    } 
?> 

<form action="<?=$_SERVER['PHP_SELF'];?>" method="post"> 
    <input type="submit" name="start" value="Start Insert"> 
    <input type="submit" name="stop" value="Stop Insert"> 
</form> 
+0

您可能想使用'$ SHMKEY = ftok(__FILE__,session_id());'來代替會話。 – RandomSeed 2013-02-19 11:14:04

+0

假設你想允許單獨的會話,即。 – RandomSeed 2013-02-19 11:25:47

+0

是的,它適用於不同的會話,我的意思是你可以從一個會話開始並從不同的會話中刪除它。 – Boynux 2013-02-19 15:09:43

1

因爲它已被告知:

  • 在當前的代碼

    ,你實際上是關閉一個不同的連接(在if(isset($_POST['stop']))分支)

  • 您不能在PHP腳本中共享與MySQL的連接,因爲您無法在會話中存儲資源

您可能,但是,存儲連接idkill這種連接從另一個腳本:

$conn = mysqli_connect($dbhost, $dbuser, $dbpass); 

if(isset($_POST['start'])) { 

    // store current connection ID 
    // store an array of connection ID's in case several connections may run simultaneously 
    $result = mysqli_query($conn, 'SELECT CONNECTION_ID()'); 
    $row = mysql_fetch_row($result); 
    $_SESSION['connection_id'] = $row[0]; 

    // close session file 
    // or else concurrent scripts using the same session will be blocked 
    session_write_close(); 

    // do actual work here 
    sleep(10); 

    // keep in mind the connection may be killed from another script at any time, e.g. 
    if (mysqli_query("...") == false) { 
     // connection was probably killed 
    } 

    // reopen session (optional, do it only if you need your session data later) 
    session_start(); 

} else if(isset($_POST['stop'])) { 

    // kill pending connection(s) 
    mysqli_kill($conn, $_SESSION['connection_id']); 
    // equivalent query in pure (My)SQL : 'KILL ' . $_SESSION['connection_id']   
} 

相反的KILL [connection_id],你可以使用KILL QUERY [connection_id]。這將終止任何正在運行的查詢,但不會關閉連接(但在您的情況下,您可能想要關閉連接)。

2

在此頁每個答案轉身一點:

  • 份額幾個PHP HTTP reqests處理

當然,最主要的問題是,PHP是一個share nothing東西之間的事情。

所以有人建議使用會話,這可能很難做到,因爲會話在關閉之前不會被重新讀取,並且您可能會很容易地覆蓋會話中的數據。其他人則建議共享內存或APC。

我們正在談論某種外部semaphore。當然,解決方案並不是要關閉連接,而是要打破外部信號的循環。

但是,您已經擁有一個大的,簡單的,也許太明顯的共享系統。 您的數據庫連接。

只需在數據庫中檢查早期循環說明。

數據庫通常會爲此任務提供諮詢鎖系統。例如使用GET_LOCKRELEASE_LOCK指令。在主插入循環的每次迭代中使用IS_FREE_LOCK,並通過停止操作獲取此鎖將是實現它的一種方法。解除鎖定的問題,可能是從所有記錄的插入循環或一段時間後的另一個信號。但你也可以管理你自己的基於表格的系統。

諮詢鎖系統的一個'優勢'是他們忽略了交易。如果您構建了自己的基於表的系統(如果不是可序列化的事務,那麼可以),使用事務必須確保寫入其他事務。

使用數據庫共享PHP實例之間的信息通常是LAMP中的默認情況,並且您保證在插入情況下使用此工具,而APC則不是這種情況。