0

これはどこかのコードの問題だと思いますが、コードはとても単純なので、それが何であるかわかりません。

wait_timeoutが十分に高いことを確認し、ここですべてを実行しました:http ://dev.mysql.com/doc/refman/5.1/en/gone-away.html成功しませんでした。

これは、1回のスクリプト実行で実行された2番目のクエリで再現可能に発生するため、コーディングエラーであると確信しています。

シングルトンデータベースハンドルを持つために、PDOクラスの周りに非常に単純なラッパーを作成しました。

<?php

class PDOWrapper
{
    protected static $instance;
    protected $dbh;

    function __construct()
    {
        if ( is_null(static::$instance) )
        {
            static::$instance = $this;
            $this->connect_to_db();
        }
    }

    static function instance()
    {
        if ( is_null(static::$instance) )
        {
            new static;
        }

        return static::$instance;
    }

    private function connect_to_db()
    {
        $db_info = array(
            0 => array(
                'hostname' => "Host",
                'username' => "User",
                'password' => "Pass",
                'db' => "DB",
            )
        );

        //Try to connect to the database
        try 
        {
            $dbh = new PDO('mysql:host=' . $db_info[0]['hostname'] . ';dbname=' . $db_info[0]['db'], $db_info[0]['username'], $db_info[0]['password'], array( PDO::ATTR_PERSISTENT => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => true ));
        }
        catch (PDOException $e)
        {
            log_message("Error connecting to DB!: " . $e->getMessage(), LOG_LEVEL_CRITICAL );
            return false;
        }

        $this->dbh = $dbh;
    }

    public static function get_dbh()
    {
        if ( is_null(static::$instance) )
        {
            new static;
        }

        return static::$instance->dbh;
    }
}

次に、次のようにラッパーを使用します。

function somefunc(){
    $dbh = PDOWrapper::get_dbh();
    $future_sth = $dbh->prepare("SELECT * FROM some_table");
    $future_sth->execute();
    $ret = $future_sth->fetchAll(PDO::FETCH_ASSOC);
    print_r($ret);
    $future_sth->closeCursor();
    return $ret;
}

イベントループの一部として、この関数を繰り返し呼び出します。初めて呼び出すと、print_rは正常に実行され、期待する行が出力されます。

ただし、関数を1回実行すると、次のようになります。

Warning: Error while sending QUERY packet. PID=92871
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 2006 MySQL server has gone away'

なぜ「なくなった」のかわかりません。私のmy.cnfは問題ないようです。待機タイムアウトは非常に大きく、とにかく2番目のクエリを実行するとすぐに発生します。何か案は?

MySQLエラーログでは明らかに何かが間違っているようには見えません。

120925 12:48:46 mysqld_safe Starting mysqld daemon with databases from /usr/local/var/mysql
120925 12:48:46 [Warning] The syntax '--log' is deprecated and will be removed in a future release. Please use '--general-log'/'--general-log-file' instead.
120925 12:48:46 [Warning] Setting lower_case_table_names=2 because file system for /usr/local/var/mysql/ is case insensitive
120925 12:48:46 InnoDB: The InnoDB memory heap is disabled
120925 12:48:46 InnoDB: Mutexes and rw_locks use GCC atomic builtins
120925 12:48:46 InnoDB: Compressed tables use zlib 1.2.5
120925 12:48:46 InnoDB: Initializing buffer pool, size = 128.0M
120925 12:48:46 InnoDB: Completed initialization of buffer pool
120925 12:48:46 InnoDB: highest supported file format is Barracuda.
120925 12:48:46  InnoDB: Waiting for the background threads to start
120925 12:48:47 InnoDB: 1.1.8 started; log sequence number 2273680401
120925 12:48:47 [Note] Server hostname (bind-address): '0.0.0.0'; port: 3306
120925 12:48:47 [Note]   - '0.0.0.0' resolves to '0.0.0.0';
120925 12:48:47 [Note] Server socket created on IP: '0.0.0.0'.
120925 12:48:47 [Note] Event Scheduler: Loaded 0 events
120925 12:48:47 [Note] /usr/local/Cellar/mysql/5.5.25a/bin/mysqld: ready for connections.
Version: '5.5.25a-log'  socket: '/tmp/mysql.sock'  port: 3306  Source distribution
4

1 に答える 1

4

私はそれを考え出した。

を使用してマルチプロセスデーモンに取り組んでいましたpcntl_fork。親プロセスは、ループを実行してデータベースにクエリを実行し、表示されたデータに応じて子をフォークして追加の作業を実行する責任がありました。

子供たちはDB接続を必要としませんでしたが、pcntl_fork使用されたため、DB接続が与えられました。私はexit()、子プロセスが作業を終えたときに子プロセスを強制終了するために使用していました。これにより、「フレンドリーな」PHPクリーンアップにより、子が持つと認識されたアクティブなMySQL接続が閉じられました。

制御は親に戻ります。親は、データベースでさらにデータを見つけて子に送信しようとすると、DB接続が突然無効になったことを認識します。

私にとっての修正は、posix_kill(getmypid(), 9);ではなく子供を殺すために使用することでしたexit();

于 2012-09-25T21:00:08.777 に答える