セッションのデッドロックによる管理画面のフリーズについて

プログラム(機能)関連の開発の話題
返信する
jeyson
メンバー
メンバー
記事: 26
登録日時: 2010年7月20日(火) 11:31

セッションのデッドロックによる管理画面のフリーズについて

投稿記事 by jeyson »

MODXを使用する際に「読み込み中」のまま、画面が固まってしまい、次の操作に移るどころか、ログインし直そうとしても、全てが固まってしまい、何もできない状態になることが発生することがあります。
これはネットワークが重い環境や、アクセス負荷の高いサイトで頻発するようです。
1分ぐらい待つと解消されるのですが、はっきり言って待つ時間は最低の時間です。

この現象について原因が判明したので共有させていただきます。

原因はPHPセッションのデッドロックでした。
https://unsolublesugar.com/20121103/113321/

MODXの管理画面では複数のAPIが同時に走っているため、どこかで処理が滞ると発生します。
どこかで処理が握られてしまい、次の処理が走らない状態になります。

対処コードとしては
MODXのセッションをDBセッションにする形以外には思いつかなかったので下記のように対処しました。

1.
添付のファイル「session_db.php」を
/manager/includes/
に配置します。

2.
下記のSQLを発行します。

コード: 全て選択

DROP TABLE IF EXISTS `modx_tbl_session`;
CREATE TABLE IF NOT EXISTS `modx_tbl_session` (
  `session_id` varchar(50) NOT NULL,
  `session_data` text DEFAULT NULL,
  `create_date` int(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `modx_tbl_session`
  ADD PRIMARY KEY (`session_id`);
3.
/manager/includes/config.session.php
というファイルを作成し
下記のようなコードを入れます。

コード: 全て選択

<?php
$database_server             = 'localhost';
$database_user               = 'xxxx';
$database_password           = 'xxxxx';
$dbase                       = 'xxxxxxx';
※xxxxの部分は各自適切なものを

4.
/manager/includes/initialize.functions.inc
に下記のようなものを加えます。

コード: 全て選択

<?php
include_once('session_db.php');  ← これを加える
// start cms session
function startCMSSession() {
    global $site_sessionname;
    $_ = crc32(__FILE__);
    $_ = sprintf('%u', $_);
    $_ = base_convert($_,10,36);
    $site_sessionname = 'evo' . $_;

    if (MODX_DB_SESSION_OK) {  ← これを加える
        $mysql_sesshandler = new MySessionHandler();  ← これを加える
        session_set_save_handler($mysql_sesshandler, true);  ← これを加える
    }  ← これを加える

    session_name($site_sessionname);
    session_set_cookie_params(0,MODX_BASE_URL);
    session_start();
    
正直に言って、きれいな対処ではないです。
ですが
initialize.functions.inc

/manager/includes/config.inc.php
で読み込みされる
/manager/includes/initialize.inc.php
の中でさらに読み込みされるファイルです。

そして、startCMSSessionファンクションは
DBモジュールが読み込みされる前にコールされています。

さらに
/manager/session_keepalive.php

ダイレクトに
/manager/includes/document.parser.class.inc.php
を読み込みしてからスタートするという素直な読み込み順序ではないのです。

きれいじゃないけど、
ひとまずはこれで現在は対処してうまく動いているようです。
添付ファイル
session_db.zip
(1.22 KiB) ダウンロード数: 423 回
アバター
yama
管理人
記事: 3236
登録日時: 2009年7月29日(水) 02:50

セッションのデッドロックによる管理画面のフリーズについて

投稿記事 by yama »

わざわざ調べていただいたのに確認が遅くなってすみません。
DBセッション、いずれ対応せねばとは思っていました。後ほど確認してみます。
jeyson
メンバー
メンバー
記事: 26
登録日時: 2010年7月20日(火) 11:31

セッションのデッドロックによる管理画面のフリーズについて

投稿記事 by jeyson »

あれから運用してみて、欠点がありましたので以下対処版を配置します。

まず、セッションに格納するデータがtext型では収まりきらないことがわかりました。
下記が安定したSQLです。
DROP TABLE IF EXISTS `modx_tbl_session`;
CREATE TABLE IF NOT EXISTS `modx_tbl_session` (
`session_id` varchar(50) NOT NULL,
`session_data` mediumtext DEFAULT NULL,
`create_date` int(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `modx_tbl_session`
ADD PRIMARY KEY (`session_id`);

次にセッション関数ですがガベージコレクションを実装していなかったです。
下記が正しいコードになります。
添付ファイル
session_db.php.zip
(1.7 KiB) ダウンロード数: 361 回
アバター
yama
管理人
記事: 3236
登録日時: 2009年7月29日(水) 02:50

セッションのデッドロックによる管理画面のフリーズについて

投稿記事 by yama »

いろいろありがとうございます、すぐには難しいかもしれませんが
できるだけ採用の方向で調整しますね。
アバター
yama
管理人
記事: 3236
登録日時: 2009年7月29日(水) 02:50

セッションのデッドロックによる管理画面のフリーズについて

投稿記事 by yama »

コード: 全て選択

CREATE TABLE IF NOT EXISTS `{PREFIX}system_sessions` (
  `session_id` varchar(40) NOT NULL,
  `previous_id` varchar(40) NOT NULL,
  `payload` longtext NOT NULL,
  `createdon` int(11) unsigned NOT NULL DEFAULT '0',
  `updatedon` int(11) unsigned NOT NULL DEFAULT '0',
  `ip_address` varchar(40) NOT NULL,
  `user_agent` varchar(255) NULL,
  `unique_hash` char(32) NOT NULL DEFAULT '',
  PRIMARY KEY (`session_id`),
  UNIQUE KEY `PREVIOUS` (`previous_id`)
);
今のところこんな感じで調整中です。
返信する