2013-02-15 114 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则不是这种情况。