web-dev-qa-db-ja.com

session_start()には非常に長い時間がかかります

私のサイトの動作が非常に遅い(そして私はその理由について何も知りませんでした)。これはZend Applicationに基づいており、以前はそのようなサイトを数十ほど作成していたので、MYコードは大丈夫だと確信しています。

私はxdebuggerをサーバーにインストールし、それをプロファイルして何を推測しようとしましたか? php :: session_start()は48.675秒かかりました。 48秒半!信じられない!これの理由は何でしょうか?これは一般的な操作ですが、なぜ実行できるのですかSO long?そのような動作を修正する方法、どの構成を編集するのですか?Googleで検索しましたが、良い答えは見つかりませんでした)前に感謝します!

xdebugger profiling results

22
ABTOMAT

session_start(セッションがファイルに保存されている)はPHPでブロックされているため、同じブラウザーセッション(AJAXまたは複数のブラウザータブ/ウィンドウ)で複数のサーバーセッションを開始しようとすると、この問題が発生します。各session_startは、他のセッションが終了するまで待機します。

ここを参照してください: http://konrness.com/php5/how-to-prevent-blocking-php-requests/

ファイルからセッションのデータベースストレージに変更してみてください。

19

私の推測は、ネイティブsession_start()関数内で実行されるガベージコレクションルーチンでしょう。たぶん、最大寿命を変更するなど、多くの古いセッションファイルを保持する何かをしたことがありますか?または、データベースに保存することをお勧めしますが、適切なインデックスを作成するのを忘れましたか?ネイティブGCルーチンstat()は、有効期限をチェックするためのすべての単一セッションファイルです。多くのファイルが作成されている場合、これは時間がかかります。

edit:デバッグのみを支援します、ガベージコレクションを一時的に無効にします設定 session.gc-probability

session.gc-probability = 0

設定が固まっていることを確認してください。ZendFrameworkがここで何をしているのかわかりません。

追伸原因を知らずに修正を提案することは困難です。私の答えは、原因の特定に向けてあなたを導くことを意図しています。

19
goat

私はこの問題を抱えており、この特定の応答を誰も投稿していないことに驚いています。それはそうではないかもしれませんが、チェックする価値があります。

PHPは、ページの処理中にセッションファイルをロックするため、そのページはページに排他的にアクセスできます。考えてみてください。sess_184c9aciqocファイルはデータベースではないため、同じセッションの2つの呼び出しから同時にアクセスすることはできません。したがって、ajax呼び出しが多い場合、「トラフィックジャム」が発生する可能性があります。高度なスクリプトを作成し始めると、これは注意すべき問題です。ちなみに、ここにタイムスタンプの配列を格納する関数があります。私はこれを使用して、セッションの開始が原因であることを理解しました:

//time function for benchmarking
if( function_exists('gmicrotime')){
    function gmicrotime($n=''){
        #version 1.1, 2007-05-09
        //store array of all calls
        global $mT;
        list($usec, $sec) = explode(' ',microtime());
        if(!isset($mT['_base_']))$mT['_base_']=$sec;
    $t=round((float)$usec + (float)(substr($sec,-4)),6);
    $mT['all'][]=$t;
    if($n){
        if(isset($mT['indexed'][$n])){
            //store repeated calls with same index.  If in a loop, add a $i if needed
            if(is_array($mT['indexed'][$n])){
                $mT['indexed'][$n][]=$t;
            }else{
                $mT['indexed'][$n]=array($mT['indexed'][$n],$t);
            }
        }else $mT['indexed'][$n]=$t;    
    }
    //return elapsed since last call (in the local array)
    $u=$mT['all'];
    if(count($u)>1){
        $mT['_total_']=$u[count($u)-1] - $u[0];
        return round(1000*($u[count($u)-1]-$u[count($u)-2]),6);
    }
}
gmicrotime('pageStart');
}

次に、次のように呼び出します。

gmicrotime('beforeSessionStart');
session_start();
gmicrotime('afterSessionStart');

do_something_slow();
gmicrotime('afterSlowProcess');
//etc..
echo '<pre>';
print_r($mT);  

これがお役に立てば幸いです!

6
Samuel Fullman

別のアプローチとしては、大きなmemory_limit PHP.ini内。

PHPMyAdminに巨大なmysqlダンプをアップロードしてロード時間を急増させるために、おそらく(上記のように)現在多くのセッションファイルが積み重なっているため、PHPに余裕がありました。デフォルトは128M、 おもう。それを4倍にしました。

2
PeerBr

同じページに複数の同時ajax呼び出しがある場合、この状況により問題が発生する可能性があります。

0
Nicolas Finelli

この問題が発生しました。 session_startは約5秒かかりました。

私の問題は、その上にいくつかの変数を宣言していたことでした。

Session_startを一番上に移動したところ、数ミリ秒かかりました。

0
Shane Zammit

私の場合、/etc/php.d/memcached.iniのmemcacheサーバーの設定が正しくありませんでした ここ はmemcacheのプロパティに関する情報で、 ここ はmemcacheにストレージをセットアップする方法です。

0
vikramaditya234

この問題を回避する1つの方法は、セッションをファイルではなくデータベーステーブルに保存するようにPHPに依頼することです。

まず、このソリューションの真のクレジットとしていくつかのリンクを紹介します。

http://www.tonymarston.net/php-mysql/session-handler.html

http://shiflett.org/articles/storing-sessions-in-a-database

http://culttt.com/2013/02/04/how-to-save-php-sessions-to-a-database/

次に、これらの読み取り値から派生したコード実装:

<?php

class TLB_Sessions_in_Database
{
    private $debug;
    private $dbc;

    function __construct()
    {
        $this->debug = false;

        session_set_save_handler(
            array($this, '_open'),
            array($this, '_close'),
            array($this, '_read'),
            array($this, '_write'),
            array($this, '_destroy'),
            array($this, '_clean')
        );
    }

    function _open()
    {
        if( $this->debug ) echo '_open:'.PHP_EOL;

        if( ($this->dbc = mysql_connect(DB_Host, DB_USER, DB_PASSWORD)) !== false )
        {
            $select_db = mysql_select_db(DB_NAME, $this->dbc);
            $set_charset = mysql_set_charset(DB_CHARSET, $this->dbc);

            if( $this->debug ) echo '- return: '.(( $select_db && $set_charset ) ? 'true' : 'false').PHP_EOL;

            return( $select_db && $set_charset );
        }
        else
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( false );
    }

    function _close()
    {
        if( $this->debug ) echo '_close:'.PHP_EOL;

        return( mysql_close($this->dbc) );
    }

    function _read($session_id)
    {
        if( $this->debug ) echo '_read:'.PHP_EOL;

        $session_id = mysql_real_escape_string($session_id);

        $sql = "SELECT `session_data` FROM `".DB_NAME."`.`php_sessions` WHERE `session_id` = '".$session_id."'";

        if( $this->debug ) echo '- query: '.$sql.PHP_EOL;

        if( ($result = mysql_query($sql, $this->dbc)) !== false )
        {
            if( !in_array(mysql_num_rows($result), array(0, false), true) )
            {
                $record = mysql_fetch_assoc($result);

                return( $record['session_data'] );
            }
        }
        else
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( '' );
    }

    function _write($session_id, $session_data)
    {
        if( $this->debug ) echo '_write:'.PHP_EOL;

        $session_id = mysql_real_escape_string($session_id);
        $session_data = mysql_real_escape_string($session_data);

        //$sql = "REPLACE INTO `php_sessions` (`session_id`, `last_updated`, `session_data`) VALUES ('".$session_id."', '".time()."', '".$session_data."')";
        $sql = "INSERT INTO `".DB_NAME."`.`php_sessions` (`session_id`, `date_created`, `session_data`) VALUES ('".$session_id."', NOW(), '".$session_data."') ON DUPLICATE KEY UPDATE `last_updated` = NOW(), `session_data` = '".$session_data."'";

        if( ($result = mysql_query($sql, $this->dbc)) === false )
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( $result );
    }

    function _destroy($session_id)
    {
        if( $this->debug ) echo '_destroy:'.PHP_EOL;

        $session_id = mysql_real_escape_string($session_id);

        $sql = "DELETE FROM `".DB_NAME."`.`php_sessions` WHERE `session_id` = '".$session_id."'";

        if( ($result = mysql_query($sql, $this->dbc)) === false )
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( $result );
    }

    function _clean($max)
    {
        if( $this->debug ) echo '_clean:'.PHP_EOL;

        $sql = 'DELETE FROM `'.DB_NAME.'`.`php_sessions` WHERE `last_updated` < DATE_SUB(NOW(), INTERVAL '.$max.' SECOND)';

        if( ($result = mysql_query($sql, $this->dbc)) === false )
        {
            if( $this->debug ) echo '- error: '.mysql_error($this->dbc).PHP_EOL;
        }

        return( $result );
    }
}

new TLB_Sessions_in_Database();

終わり。

0