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>

Webサイトには、レコードを繰り返し挿入するための挿入と、挿入を停止するための停止の2つのボタンがあります。ただし、MySQLのクローズ接続を使用してみました。PHPでは機能しなくなりますが、アクティビティはそのまま残ります。挿入は引き続き実行されます。問題を解決する方法は?ありがとう。

4

5 に答える 5

2

PHPではリクエスト間でリソースを共有できないため(AFAIK)、別のリクエストでプロセスを停止するこの機能を実現する方法がいくつかあります。

最初に次の行を追加します。

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

次に、forステートメントをwhileに置き換えます(この動作を変更できる場合は、イテレーションの数を気にしないようです):

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

と置換する:

while ( $_SESSION['continue'] )

接続を閉じて挿入を停止する代わりに、次のようにします。

mysql_close ($con)

次のように変更します:

$_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 );

終わり!

于 2013-02-15T11:58:55.437 に答える
2

このページのすべての答えは、1つのポイントを好転させています。

  • 複数のPHPhttpreqestsハンドラー間で何かを共有する

そしてもちろん、主な問題は、phpがシェアードナッシングであるということです。

そのため、セッションを使用することを提案する人もいます。これは、セッションを閉じる前に再読み取りが行われず、セッション内のデータが非常に簡単に上書きされる可能性があるため、実行が非常に難しい場合があります。他の人は共有メモリまたはAPCを提案します。

ある種の外部セマフォについて話しています。そしてもちろん、解決策は接続を閉じるのではなく、外部信号のループを切断することです。

しかし、あなたはすでに1つの大きくて簡単な、多分あまりにも明白な共有システムを持っています。データベース接続。

ループ命令の早期終了については、データベースをチェックインするだけです。

データベースは通常、このタスクのためのアドバイザリーロックシステムを提供します。たとえば、GET_LOCKおよびRELEASE_LOCK命令を使用します。メインの挿入ループの各反復でIS_FREE_LOCKを使用し、ストップアクションでこのロックを取得することは、それを行う1つの方法です。ロックを解除する問題がある場合、記録されたすべての挿入ループからの別の信号の後、またはしばらくしてからです。ただし、独自のテーブルベースのシステムを管理することもできます。

アドバイザリロックシステムの「利点」の1つは、トランザクションを無視することです。トランザクションを使用して、独自のテーブルベースのシステムを構築する場合は、スコープ内で他のトランザクションからの書き込みが利用可能であることを確認する必要があります(シリアル化可能なトランザクションでない場合はOK)。

通常、データベースを使用してPHPインスタンス間で情報を共有することは、LAMPのデフォルトの状況であり、APCの場合とは異なり、挿入状況でこのツールを使用できることが保証されています。

于 2013-02-19T17:55:43.580 に答える
1

PHPスクリプトを呼び出すたびに、MySQLへの独自の接続が開かれ、相互に干渉することはできません。例外は次のように開かれた接続mysql_pconnect()です:それらは開いたままで共有されますが、mysql_close()で閉じることもできません。

結論:あなたがやろうとしていることはうまくいきません(そしてとにかく悪い考えです)。

代わりに、おそらく必要なのは、挿入のバックグラウンドタスクを作成し、そこで中断メッセージを確認することです(これは、 =プロセスID.STOP[PID]を持つ空のファイルのように単純な場合があります)。[PID]

アップデート:

APCを使用できませんか?

はい、APC拡張機能がインストールされていれば、このメッセージにAPCを使用できます。これは当てはまらないため、次のエラーが発生します。

31行目の/home/ext/library/public/testdb/test.phpにある未定義の関数acp_fetch()を呼び出します。

サーバーへのrootアクセス権がありますか?次に、拡張機能を自分でインストールできます。

sudo pecl install apc

このコマンドが機能しない場合は、最初にPECLインストーラーを入手する必要があります。ここを参照してください:sudo peclinstallapcはエラーを返します

于 2013-02-15T10:47:31.307 に答える
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>
于 2013-02-18T06:07:14.740 に答える
1

アドバイスされているように:

  • 現在のコードでは、実際には別の接続を閉じています(if(isset($_POST['stop']))ブランチ内)

  • セッションにリソースを保存できないため、PHPスクリプト間でMySQLへの接続を共有することはできません

ただし、接続IDを保存し、別のスクリプトからこの接続を強制終了することはできます。

$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]。これにより、実行中のクエリは終了しますが、接続は閉じられません(ただし、この場合、接続を完全に閉じたいと思うでしょう)。

于 2013-02-18T20:21:12.380 に答える