#php #fat-free-framework
#php #fat-free-framework
Вопрос:
давний скрывающийся, первый постер. Извините за любые проблемы!
Я использую FatFreeFramework, который мне очень нравится (пожертвовал немного денег). Я начал использовать сеансы с поддержкой БД ( DB SQL Session), и по большей части они работают хорошо. Версия PHP 7.4.
В моих журналах я вижу повторяющиеся 500 ошибок:
500 Внутренняя ошибка сервера: PDOStatement: Дубликат записи ‘nd4n440i8usfekd5llskhdv58e’ для ключа ‘PRIMARY’
[app / libs / db / sql/mapper.php:458] DB SQL-> exec()
[app / libs /db/cursor.php:245] DB SQL Mapper->вставить ()
[app/ libs/db/sql/session.php:97] DB Cursor-> сохранить()
Я подумал, что, возможно, слишком мало энтропии, поэтому я добавил и зарегистрировал («create_sid» функция, возвращающая случайные байты.
function genSidId(){
return bin2hex(random_bytes(40));
}
Я ссылался на него в session_set_save_handler
части класса. Session_id
стало длиннее, но это не решило повторяющиеся ошибки первичного ключа.
Вероятно, я мог бы переписать части библиотеки, чтобы проверить, session_id
существует ли она, или, может быть, использовать «заменить на» (на который я видел ссылки в некоторых похожих вопросах), но, может быть, у кого-то есть лучшее решение? Или, может быть, мне не хватает какой-то настройки в F3?
Ошибки происходят 4-6 раз в день, веб-сайт получает тысячи посещений в день.
Комментарии:
1. Есть ли у вас настройка master / slave для вашей базы данных?
2. И из любопытства вы использовали другой интерфейс для сохранения ваших сеансов в качестве теста и посмотрели, сохраняется ли проблема с использованием хранилища на основе файлов, memcached, jig и т. Д.?
3. Это общий хостинг. Существует только один сервер базы данных. Я использовал только сеансы БД на веб-сайте. До развертывания я использовал сеансы на основе файлов (по умолчанию, предоставляемые системой), но нагрузка была крошечной по сравнению с текущим количеством посетителей. Так что я бы сказал, что это неубедительно.
4. Я бы сказал, попробуйте поменять сеансы БД на сеансы на основе файлов. Я просмотрел код, который вы сделали, прочитал некоторые документы по PHP, посмотрел на класс DB SQL Session, и мне сразу ничего не бросилось в глаза. Не имеет смысла, почему он будет пытаться записать один и тот же идентификатор сеанса дважды. Если бы у вас была настройка master / slave, я мог бы пожаловаться на задержку slave, но поскольку это не так, было бы неплохо попробовать другой метод, чтобы выяснить одну из 2 вещей: либо что-то не так с реализацией сеанса SQL, либо что-то происходит с вашими настройками PHP, вызывающимипроблема.
Ответ №1:
Хорошо, я исправил ошибки, переписав DB SQL Session .
class ASession {
protected $_agent,$_ip;
function open($path,$name) {
return TRUE;
}
function close() {
return TRUE;
}
function read($id) {
$var = DB::var("SELECT data from sessions where session_id = ?", $id);
return $var ?? '';
}
function write($id,$data) {
$exists = DB::var("SELECT session_id FROM sessions WHERE session_id = ?", $id);
if (!empty($exists)){
DB::exec("UPDATE sessions SET data = ?, stamp = ?, ip = ?, agent = ? where session_id = ?", [$data, time(), $this->_ip, $this->_agent, $id]);
}else{
DB::exec("INSERT IGNORE INTO sessions(session_id, data, stamp, ip, agent) values (?, ?, ?, ?, ? )", [$id, $data, time(),$this->_ip, $this->_agent]);
}
return TRUE;
}
function destroy($id) {
DB::exec("DELETE FROM sessions where session_id = ?", $id);
return TRUE;
}
function cleanup($max) {
Log::logToFile('session_cleanup', $max);
DB::exec("DELETE FROM sessions where stamp < ?", [time() - intval($max)]);
return TRUE;
}
function genSidId(){
return bin2hex(random_bytes(40));
}
function __construct() {
session_set_save_handler(
[$this,'open'],
[$this,'close'],
[$this,'read'],
[$this,'write'],
[$this,'destroy'],
[$this,'cleanup'],
[$this, 'genSidId']
);
register_shutdown_function('session_commit');
$fw=Base::instance();
$headers=$fw->HEADERS;
$this->_agent=isset($headers['User-Agent'])?$headers['User-Agent']:'';
if (strlen($this->_agent) > 300) {
$this->_agent = substr($this->_agent, 0, 300);
}
$this->_ip=$fw->IP;
}
}
Просто проверить, существует ли session_id в БД, было недостаточно: ошибок было меньше, но все же пара. «INSERT IGNORE» исправил проблему.
У меня не было жалоб от пользователей, так что, надеюсь, сеансы работают. Мои собственные тесты были положительными.
Мне кажется, что простой, жестокий код часто лучше, чем использование слишком большого количества абстракций. Все еще люблю F3, хотя! 🙂