Почему таблица oc_session растет?

Тема в разделе "Ошибки и их решения", создана пользователем Павел Зырянов, 11 янв 2021.

  1. Павел Зырянов

    Павел Зырянов Новичок

    Сообщения:
    4
    Симпатии:
    0
    Не могу на форуме отыскать ответ на вопрос:
    Почему таблица _session растет? Собственно что растет не так страшно, страшно то что она не отчищается.
    Я не нашел ни одного места где используется функция :
    Код:
    public function gc($expire) {
            $this->db->query("DELETE FROM `" . DB_PREFIX . "session` WHERE expire < " . ((int)time() + $expire));
          
            return true;
        }
    Может я заблуждаюсь, разъясните кто знает как именно работает очищение таблицы и в какой момент запускается.
    А если я прав, и функция не вызывается, то почему это не исправлено, как исправить...
    В общем кому не все равно откликнетесь.

    Русская сборка OpenCart Version 3.0.3.2 (rs.2)
     
  2. Chukcha

    Chukcha Специалист

    Сообщения:
    3.013
    Симпатии:
    685
    Никогда


    Код:
        public function write($session_id, $data) {
            if ($session_id) {
                $this->db->query("REPLACE INTO `" . DB_PREFIX . "session` SET session_id = '" . $this->db->escape($session_id) . "', `data` = '" . $this->db->escape(json_encode($data)) . "', expire = '" . $this->db->escape(date('Y-m-d H:i:s', time() + $this->expire)) . "'");
            }
            $this->gc();
            return true;
        }
        
        public function destroy($session_id) {
            $this->db->query("DELETE FROM `" . DB_PREFIX . "session` WHERE session_id = '" . $this->db->escape($session_id) . "'");
            
            return true;
        }
        
            public function gc() {
            $gc_divisor = (int)ini_get('session.gc_divisor');
    
            if ($gc_divisor) {
                $gc_divisor = $gc_divisor;
            } else {
                $gc_divisor = 1;
            }
    
            if (ini_get('session.gc_probability')) {
                $gc_probability = ini_get('session.gc_probability');
            } else {
                $gc_probability = 1;
            }
            if (mt_rand() / mt_getrandmax() < $gc_probability / $gc_divisor) {
                $this->db->query("DELETE FROM `" . DB_PREFIX . "session` WHERE `expire` < '" . $this->db->escape(date('Y-m-d H:i:s', time())) . "'");
            }
    
            return true;
        }
    Я у себя сделал так..
     
  3. Павел Зырянов

    Павел Зырянов Новичок

    Сообщения:
    4
    Симпатии:
    0
    Браток, спасибо за ответ но не совсем понятно.
    Если функция gc не вызывается, то как это сработает, и зачем нужен рандом? (mt_rand() / mt_getrandmax() < $gc_probability / $gc_divisor)
     
  4. Chukcha

    Chukcha Специалист

    Сообщения:
    3.013
    Симпатии:
    685
    братки на зоне сидят

    Изучайте код..

    Но чтоб еще рассказывать как это работает.. :(
     
  5. fanatic

    fanatic Продвинутый пользователь

    Сообщения:
    1.415
    Симпатии:
    239
    а это что?
    для расчета вероятности, сработает очистка или нет
     
    Павел Зырянов нравится это.
  6. Павел Зырянов

    Павел Зырянов Новичок

    Сообщения:
    4
    Симпатии:
    0
    Большое спасибо.
    $this->gc(); - не заметил, искал в своем коде.
    все равно не понятно зачем расчет вероятности. :(
    Почему я не могу со сто процентной вероятностью отчищать?
    У меня в коде gc_probability присваивается только в деструкторе класса File, аналогично примеру Chukcha, может у вас какие-то версии другие и мне стоит обновиться?
    На сколько я понимаю это должно работать тогда когда срок истек а не тогда когда звезды сложились.
    Извиняюсь за занудство.

    Браток = брат = друг = товарищ = камрад. А на зоне зэки сидят, не путай понятия.
    Изучаю и изучаю.
    Да, я просил разъяснить. То что знаешь ты и очевидно для тебя, для другого может быть темный лес.

    смотрел код на https://github.com/opencart/opencart, и он кардинально отличается от моего, там функция похожая на то как сделал Chukcha но:
    $_['session_probability'] = 1; $_['session_divisor'] = 5; переменные в дефолте и не меняются
    и так за ранее известно что:
    if (round(rand(1, $this->config->get('session_divisor') / $this->config->get('session_probability'))) == 1) =>
    if (round(rand(1, 5 / 1)) == 1) => вероятность один из пяти с бессмысленными вычислениями, я так понял для того, чтоб только каждый пятый раз делать запрос к базе данных. И это при том какой запрос делается getProduct (9 вложенных запросов SELECT).
    Ответа не жду, но оочень интересно зачем это нагромождение...
     
  7. Chukcha

    Chukcha Специалист

    Сообщения:
    3.013
    Симпатии:
    685
    Потому что когда-нибудь оно очистится..
     
  8. fanatic

    fanatic Продвинутый пользователь

    Сообщения:
    1.415
    Симпатии:
    239
    при чем file.php когда речь идет о хранении сессии в базе?
     
  9. Павел Зырянов

    Павел Зырянов Новичок

    Сообщения:
    4
    Симпатии:
    0
    Мы уже отошли от темы. Но отвечу:
    Я нашел в file.php единственное упоминание gc_probability так как я не знал что это директива PHP и задается в php.ini.
    Теперь понял что это:
    session.gc_divisor в сочетании с session.gc_probability определяет вероятность запуска функции сборщика мусора (gc, garbage collection) при каждой инициализации сессии. Вероятность рассчитывается как gc_probability/gc_divisor, то есть 1/100 означает, что функция gc запускается в одном случае из ста, или 1% при каждом запросе. session.gc_divisor по умолчанию имеет значение 100.