Сесии на mysql?

REMO

Guest
Сесии на mysql?

Знаю что вопрос поднимался 1к раз, но тем на форуме очень много и очень много не по теме... поэтому решился спросить еще раз.

Прочитав Котерова и http://www.lerdorf.com/tips.pdf так и не понял.

1) Чтобы переопределить обработчики сессии не в скрипте, а в апаче (я так понимаю это все таки лучше делать в нем), что нужно прописать в .htaccess?

2) Генерить SID сесии нужно самому или это можно как то оставить на PHP, если самому то md5(time().rand(0,100)) - достаточно ли надежно для создания многообразия?

3) При организации таблицы сессий таким образом:
PHP:
CREATE TABLE sessions (
id char(32) NOT NULL,
data text,
ts timestamp,
PRIMARY KEY (id)
)
В data что пишется, при сохранении переменной сесии? У Котреова написано, что нужно Serialaize($data) и потом это в мускул, если я правильно понял. Т.е. все переменные регистрируемые в сессии хранятся в виде строки?

-~{}~ 13.05.04 15:12:

Пните хоть кто-нить :(
 

IntenT

SkyDiver
раздели задачи на 2-3 поменьше.
сначала смени хендлер сессий
потом разберись как генерится ИД
потом думай, как сериализовать массив
 

REMO

Guest
:) пнули...
спасиб конечно за пост, но это не совсем ответы на мои вопросы :(

-~{}~ 14.05.04 12:56:

Модераторы, перенестите, плиз, топик в раздел PHP для продвинутых, может там кто то ответит :(
 

_RVK_

Новичок
То ли лыжи не едут, то ли я... чего то не пойму.
REMO, скажи, зачем тебе? Что конкретно ты хочешь хранить в такой сессии? Чем тебя не устраивают обычные сессии? Вообще, опиши конкретную задачу, и тогда тебе смогут посоветовать конкретно по ней....
 

Линк

Guest
зачем сесси на Mysql?

почему не пользоваться СТАНДАРТНЫМИ сессиями php?
[f]sessions[/f] почитай
там все подробно описано

ЗЫ: Imho, Котеров не всегда понятно пишет))
 

REMO

Guest
Все просто, сейчас в директории хранения фаилов сесий 3000 фаилов, из-за этого идет подтормаживание работы фаиловой системы... Хостер порекомендовал не более 500 фаилов или перейти на использование БД для храннеия сесий.

Если посещаемость ресурса еще увеличится, будет еще хуже...
 

Фанат

oncle terrible
Команда форума
REMO
откуда у тебя столько файлов?
у тебя 3000 одновременных посетителей?
 

REMO

Guest
Автор оригинала: Фанат
REMO
откуда у тебя столько файлов?
у тебя 3000 одновременных посетителей?
Посещаемость ресурса 60к в сутки... Видимо отсюда. :) 3000 не всегда конечно, может больше, может меньше...

-~{}~ 15.05.04 00:27:

Может можно как то распределить фаилы по нескольким каталогам? Чтобы решить эту проблему...
 

Фанат

oncle terrible
Команда форума
(тихим, вкрадчивым голосом) а тормоза - только от количества файлов в каталоге, да? самое узкое место.
других не нашлось
 

REMO

Guest
Автор оригинала: Фанат
(тихим, вкрадчивым голосом) а тормоза - только от количества файлов в каталоге, да? самое узкое место.
других не нашлось
Х.з. когда не знаешь где искать, ищешь где знаешь :) Где поискать тормоза еще?

Ну от такого количества фаилов тормоза же все таки есть и не малые я думаю, так почему бы их не убрать? Сам понимаю, что перенос сесий на БД геморное дело и может не оправдать заморочек, но что еще можно сделать?

Как один из вариантов хранить фаилы сесий в нескольких каталогах... Т.е. проблема в механизме определения каталога по идентификатору сесии.
 

Фанат

oncle terrible
Команда форума
Ну от такого количества фаилов тормоза же все таки есть и не малые я думаю
а я не думаю.
Где поискать тормоза еще?
в скриптах и базе, естественно

сейччас ты напоминаешь пьяницу корый часы ищет.

если бы ты сказал - вот код, время до старта сессии и после
при 3 файлах и при 3000 - было бы о чем говорить.

заодно, глядишь, нашел бы реальный кусок, где тормоза.
имхо - в базе
 

Three Daws

Guest
Понятно...
Действительно, при наличии большого количества файлов в директории файловая система начинает подтормаживать. Экспериментальным путем получается приемлемое количество файлов что-то около 1000.

----------
2 Фанат: вообще, я как-то тебе тоже рассказывал про эту фишку с торможением FS. "Экспериментальное количество" в 1000 файлов выходило у меня, кажется у Макса и Андрея (chroot). Собственно, я от него впервые это и услышал :)

А, кстати, Женька тоже с этим сталкивался.
----------

Ок, вот пример реализации класса для работы с сессиями, хранимыми в СУБД MySQL - http://www.zend.com/zend/spotlight/code-gallery-wade8.php

Другое дело что:

1. Соединение с БД - так же ресурсоемкая операция. Наличие выигрыша еще надо оценить. Хотя, если Вы всегда соединяетесь с БД и все время работаете с базой - Вы все равно порождаете соединение, так что дополнительных расходов тут может и не быть.

2. Реально ли необходимы эти самые сессии? Или, говоря о количестве посетителей Вы имеете ввиду количество авторизованных пользователей, для которых необходима персонификация информации?

Если Вы используете механизм сессий не только для отслеживания именно персонифицированных данных, я бы (на вашем месте, при такой посещаемости) постарался исключить лишнее использование сессий.
 

_RVK_

Новичок
REMO, почти на все твои вопросы можно ответить, просто попробовав. Вот в мане есть много примеров. http://www.php.net/session_sat_save_handler
Попробуй сделай так, потом этак. Потестируй, и с цифрами сюда. Всем, думаю, интересно будет.
 

Линк

Guest
при наличии большого количества файлов в директории файловая система начинает подтормаживать.
звучит как "на очень сложных алгоритмах, компиляторы тормозят". Как вы думаете, работают почтовые сервера с десяткми тысяч файлов в очереди?;')

[off]
а может купить колокейшен, и перейти на более удачную FS? например на FS с хешовым оглавлением? :) или на более удачный винт?
попросить ядро пореже сбрасывать буферы?
юзать ramdrive в конце концов))))))))) самый простой и дешевый способ))
[/off]
 

Three Daws

Guest
[off]
2 Линк: явление имеет место быть и себя проявлять вне зависимости от вашего мнения. Проявляется оно и на выделенном сервере.

Вообще-то одним из решения является динамическое формирование поддиректорий и равномерное распределение по ним хранимых файлов.

Компиляторы действительно тормозят на более сложных алгоритмах и с точки зрения программы на ассемблере выгоднее разворачивать операцию возведения в степень в последовательное умножение, а умножение - в сложение.

Хотите поговорить об этом?

А компания IBS действительно предлагает в качестве решения проблем с производительностью Java-Приложений работающих под управлением сервера приложений Веб-Сфера отдельный сервер, носящий продажное названия "Веб-Сфера тюннинг" и оснащенный 4-мя гигабайтами оперативной памяти.

Еще можно поговорить о кластерах, дополнительном роутере, автоматически уравнивающем присутствие посетителей по серверам в кластере и т.п.

Хотите поговорить об этом?
[/off]

-~{}~ 18.05.04 03:52:

Довольно трудно рассуждать об эффективности кода и архитектуры системы в целом, опираясь на то, что человек просто задал тот или иной вопрос. Особенно, если он не начинает попутно выяснять, как ему лучше написать условный оператор.

Не думаю, что привести ссылку на реализацию того самого класса, который занимается хранением сессий в БД MySQL в данном случае неверно с моей стороны.

Жаль, что это так выбивается из традиций данного форума, что влечет рассуждения о каких-то продвинутых операционных системах и т.п.

Кстати, я имею представление о том как работают почтовые сервера. И не только об этом.
 

whirlwind

TDD infected, paranoid
PHP:
/*
    require php 4.2.0 +
*/

if (!class_exists('HttpSession')){
include('UsrProfile.inc');
class HttpSession extends UsrProfile{

    function OpenSession($path,$name){
        $errh = "HttpSession::OpenSession:";
        $this->mlog($errh,ML_DEBUG_CALL);

        $this->Connect();
        return $this->OnSessionOpen();
    }

    function CloseSession(){
        $errh = "HttpSession::CloseSession:";
        $this->mlog($errh,ML_DEBUG_CALL);

        $this->OnSessionClose();
        $this->CloseConnection();
        return true;
    }

    function ReadSession($id){
        $errh = "HttpSession::ReadSession:";
        $this->mlog($errh,ML_DEBUG_CALL);

        if (!$this->IsConnected()){
            $this->mlog("$errh Not connected.");
            return '';
        }

        if (1 != $this->IsSessionExists($id)){
            // Если записи нет или она просрочена, загружаем дефолтный профиль.
            $this->SelectProfile(UID_GUEST);
            $this->OnSessionRead();
            return '';
        }

        // Указанная сессия уже существует. Загрузим и распакуем профиль.
        $qtext = sprintf("SELECT vars,uid FROM sessions WHERE SID='%s'",$this->Quote($id));
        if (!$this->Select($qtext)){
            return '';
        }

        if (!$vars = $this->NextHashRef()){
            return '';
        }

        // Выбираем указанный профиль
        if (!$this->SelectProfile($vars['UID'])){
            $this->SelectProfile(UID_GUEST);
            $vars['VARS'] = '';
        }
        $this->OnSessionRead();
        return $vars['VARS'];
    }

    function WriteSession($id,$dt){
        $errh = "HttpSession::WriteSession:";
        $this->mlog($errh,ML_DEBUG_CALL);

        if (!$this->IsConnected()){
            $this->mlog("$errh Not connected.");
            return false;
        }

        if (!$this->OnSessionWrite()){
            return false;
        }

        $qtext = sprintf("LASTACS=%d,UID=%d,VARS='%s'",intval(time() / 60),
            $this->GetProfileUID(),$this->Quote($dt));

        $exists = $this->IsSessionExists($id);

        if (-1 == $exists || 0 == $exists){
            $qtext = sprintf("%s,CREATED=%d",$qtext,intval(time() / 60));
        }

        if (0 != $exists){
            // Обновление
            $qtext = sprintf("UPDATE sessions SET %s WHERE SID='%s'",
                $qtext,$this->Quote($id));
        }else{
            // Вставка
            $qtext = sprintf("INSERT INTO sessions SET SID='%s',%s",
                $this->Quote($id),$qtext);
        }

        if (!$this->DoQuery($qtext)){
            return false;
        }
        return true;
    }

    function DestroySession($id){
        $errh = "HttpSession::DestroySession:";
        $this->mlog($errh,ML_DEBUG_CALL);

        if (!$this->IsConnected()){
            $this->mlog("$errh Not connected.");
            return false;
        }

        if (!$this->OnSessionDestroy()){
            return false;
        }

        $qtext = sprintf("DELETE FROM sessions WHERE SID='%s'",
            $this->Quote($id));
        if (!$this->DoQuery($qtext)){
            return false;
        }
        return true;
    }

    function GarbageCollector($maxttl){
        $errh = "HttpSession::GarbageCollector:";
        $this->mlog($errh,ML_DEBUG_CALL);

        if (!$this->IsConnected()){
            $this->mlog("$errh Not connected.");
            return false;
        }

        $qtext =sprintf("DELETE FROM sessions WHERE LASTACS<%d",
            intval((time() - ini_get('session.gc_maxlifetime')) / 60));
        if (!$this->DoQuery($qtext)){
            return false;
        }
        return true;
    }

    function IsVarExists($varname){
        if (isset($_SESSION[$varname])){
            return true;
        }
        return false;
    }

    function SetVar($varname,$value){
        $_SESSION[$varname] = $value;
        return true;
    }

    function GetVar($varname){
        return $_SESSION[$varname];
    }

    function IsSessionExists($id){
        $errh = "HttpSession::IsSessionExists:";
        $this->mlog($errh,ML_DEBUG_CALL);

        if (!$this->IsConnected()){
            $this->mlog("$errh Not connected.");
            return false;
        }

        $maxttl = intval(ini_get('session.gc_maxlifetime') / 60);
        $expire = intval(time() / 60) - $maxttl;

        $qtext = sprintf("SELECT LASTACS FROM sessions WHERE SID='%s'",
            $this->Quote($id));

        if (!$this->Select($qtext)){
            return 0;
        }

        // Проверим кол-во записей в выборке.
        if (0 == $this->ResultRows()){
            // Запись под указанным SID не найдена.
            return 0;
        }

        $result = $this->NextHashRef();
        if (intval((time() - ini_get('session.gc_maxlifetime')) / 60)
            > $result['LASTACS'])
        {
            // Запись просрочена.
            return -1;
        }
        return 1;
    }

    function BeginSession(){
        $errh = "HttpSession::BeginSession:";
        $this->mlog($errh,ML_DEBUG_CALL);

        ini_set('session.save_handler','user');
        ini_set('session.gc_probability',15);
        ini_set('session.name','SID');
        session_set_save_handler(
            array(& $this, 'OpenSession'),
            array(& $this, 'CloseSession'),
            array(& $this, 'ReadSession'),
            array(& $this, 'WriteSession'),
            array(& $this, 'DestroySession'),
            array(& $this, 'GarbageCollector')
        );
        session_start();

        $this->OnReady();
        return true;
    }

// virtual:

    function OnSessionOpen(){
        $errh = "HttpSession::OnSessionOpen:";
        $this->mlog($errh,ML_DEBUG_CALL);

        return true;
    }

    function OnSessionClose(){
        $errh = "HttpSession::OnSessionClose:";
        $this->mlog($errh,ML_DEBUG_CALL);

        // We need to update profile record at every page
        $this->UpdateProfile();

        return true;
    }

    function OnSessionRead(){
        $errh = "HttpSession::OnSessionRead:";
        $this->mlog($errh,ML_DEBUG_CALL);

        // Counters increment
        $this->_profile_fields['PAGES_CNT'] ++;
        $this->_profile_fields['ACS_TIME'] = intval(time() / 60);

        return true;
    }

    function OnSessionWrite(){
        $errh = "HttpSession::OnSessionWrite:";
        $this->mlog($errh,ML_DEBUG_CALL);

        return true;
    }

    function OnSessionDestroy(){
        $errh = "HttpSession::OnSessionDestroy:";
        $this->mlog($errh,ML_DEBUG_CALL);

        return true;
    }

    function OnReady(){
        $errh = "HttpSession::OnReady:";
        $this->mlog($errh,ML_DEBUG_CALL);

        return true;
    }
}}
 
Сверху