MYSQL close connect无法暂停insert活动

时间:2013-02-15 10:38:51

标签: php mysql database insert

<?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中停止运行,但活动仍然存在。插入仍然保持执行。如何解决问题?感谢。

5 个答案:

答案 0 :(得分:2)

由于PHP不允许您在请求者之间共享资源(AFAIK),因此有几种方法可以实现在另一个请求中停止进程的能力:

首先添加以下行:

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

然后用while替换你的for语句(看起来你不关心itterations的数量,如果是这样你可以改变这种行为):

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

替换为:

while ( $_SESSION['continue'] )

而不是关闭连接以停止插入执行此操作:

mysql_close ($con)

将按照:

$_SESSION['continue'] = false;

注意:不要忘记在脚本开头调用session_start()。 多数民众赞成。

如果不是这种情况你可以使用ACP ore SHM,我认为你想要停止同一会话中的页面。例如:

替换:

$_SESSION['continue'] = true

with:

apc_store( 'continue', true );

while ( $_SESSION['continue'] )

使用:

while ( acp_fetch ('continue') )

$_SESSION['continue'] = false;

使用:

apc_store( 'continue', false );

完成!

答案 1 :(得分:2)

本页中的每个答案都转过一点:

  • 在几个PHP http请求处理程序之间共享内容

当然主要的问题是php是一个share nothing的东西。

因此有人建议使用会话,这可能很难做到,因为会话在关闭之前不会重新读取,您可能很容易在会话中覆盖数据。其他人建议使用共享内存或APC。

我们谈论的是某种外部semaphore。当然,解决方案不是关闭连接,而是打破外部信号的循环。

但是你已经拥有了一个大而简单,可能太明显的共享系统。 您的数据库连接。

只需在数据库中检查循环说明的早期结束。

数据库通常为此任务提供顾问锁系统。例如,使用GET_LOCKRELEASE_LOCK说明。在主插入循环的每次迭代中使用IS_FREE_LOCK并使用停止操作获取此锁定将是一种方法。由于释放锁定的问题,可能是在来自所有记录的插入循环的另一个信号之后,或者在一段时间之后。但您也可以管理自己的基于表的系统。

咨询锁系统的一个“优势”是它们忽略了交易。如果您构建自己的基于表的系统,则必须确保使用事务处理来确保其他事务的写入可用(如果不是可序列化的事务,则确定)。

使用数据库在PHP实例之间共享信息通常是LAMP中的默认情况,并且保证在插入情况下使用此工具,而APC不是这种情况。

答案 2 :(得分:1)

每次调用PHP脚本都会打开自己与MySQL的连接,并且它们不会相互干扰。与mysql_pconnect()打开的连接是一个例外:它们保持打开状态并将被共享,但也可以使用mysql_close()关闭

结论:你要做的事情是行不通的(无论如何都是个坏主意)。

您可能需要的是为插入创建后台任务并检查其中的中断消息(可能就像空文件.STOP[PID]一样简单[PID] =进程ID)

<强>更新

  

我可以不使用APC吗?

是的,只要安装了APC扩展程序,可以使用APC获取此消息。情况并非如此,因此出现此错误:

  

在第31行的/home/ext/library/public/testdb/test.php中调用未定义的函数acp_fetch()

您是否拥有服务器的root权限?然后你可以自己安装扩展程序:

sudo pecl install apc

如果此命令不起作用,您需要先获取PECL安装程序,请参阅此处:sudo pecl install apc returns error

答案 3 :(得分: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>

答案 4 :(得分: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]。这将终止任何正在运行的查询但不会关闭连接(但在您的情况下,您可能希望完全关闭连接)。