PDA

Просмотр полной версии : [Вопрос] По поводу кэширования mysql



danya9877
19.03.2017, 18:25
Речь идет о r40/r41.
На сколько я понял, речь идет совершенно не об Mysql-кэшировании (сохранении результата запроса для быстрого ответа при повторном запросе). Тут уже фича павна.
Понятно, что при запросе виде tquery возвращается кэш (что такое non-threated query в случае использования mysql_query, если мне, допустим, не нужно возвращать кэш?)
Понятно, что при возвращении кэша из tquery он передается в указанную в параметрах функцию. Что такое тип "r (reference(ссылка))". Я так понимаю, кэш очищается автоматически при выходе из функции и нет необходимости использовать cache_delete().

Также, допустим, как в Wiki, я хочу использовать в массиве игрока кэш (вместо pSkin использовать Cache:pSkin). Есть ли профит делать это для данных, которые я не записываю обратно и не изменяю? Например, закешировать однажды reg-IP игрока и при подгружении из мода загружать его в кэш-переменную и держать там всегда (при отключении делать cache_delete()).

Буду рад любым высказываниям на основе опыта/знаний.

DeimoS
20.03.2017, 00:25
Очень сложно из всего написанного выделить хоть какой-то конкретный вопрос, но я попробую...




Речь идет о r40/r41.
На сколько я понял, речь идет совершенно не об Mysql-кэшировании (сохранении результата запроса для быстрого ответа при повторном запросе). Тут уже фича павна.

Именно. Только не Pawn, а SA-MP. Точнее, плагина.
Кэшем являются данные, возвращённые в результате обработки MySQL запроса, с которыми можно работать на стороне SA-MP сервера. Кэш возвращают лишь три вида запросов: SELECT, SHOW и DESCRIBE. SHOW и DESCRIBE в SA-MP практически не найдёшь применения.



Понятно, что при запросе виде tquery возвращается кэш

mysql_query так же может возвращать кэш. Отличие mysql_tquery от mysql_query в том, что первая отправляет обработку запроса в отдельный поток, в результате чего сервер может продолжать выполнять другие действия, пока MySQL не вернёт результат. А вторая обрабатывает всё в одном запросе, заставляя сервер подвисать, пока запрос не будет получен.



Что такое тип "r (reference(ссылка))".

Возможность указывать в качестве передаваемого параметра массив, результат которого будет перезаписан при изменении переданного значения.
Криво объяснил... В общем, будет то же самое:

main()
{
new string[] = "test";
print(string);//Выведет "test"
SomeFunc(string, sizeof(string));
print(string);//Выведет "tttt"
}

stock SomeFunc(string[], len)
{
format(strong, len, "tttt");
return 1;
}


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

Да, если ты не сохранил кэш с помощью cache_save.


Также, допустим, как в Wiki, я хочу использовать в массиве игрока кэш (вместо pSkin использовать Cache:pSkin). Есть ли профит делать это для данных, которые я не записываю обратно и не изменяю? Например, закешировать однажды reg-IP игрока и при подгружении из мода загружать его в кэш-переменную и держать там всегда (при отключении делать cache_delete()).

Ты не совсем правильно понял пример в wiki.
Там при входе на сервер происходит запрос в базу данных с выборкой всей информации о игроке. После этого в массив загружается исключительно пароль (для дальнейшей сверки с тем, что вводит игрок) и ничего более, а сам кэш сохраняется и в массив "Player[playerid][Data]" записывается ID кэша.
Далее, если игрок вводит верный пароль, происходит обращение к записанному кэшу по его ID и последующая загрузка данных их кэша (точно такими же функциями, как и, например, в mysql_tquery) и кэш удаляется. Если игрок вышел и кэш всё ещё существует (например, он отказался от ввода пароля и вышел) - так же удаление.
Сделано это для того, чтоб не посылать повторный запрос в базу данных для загрузки аккаунта в случае, если игрок ввёл верный пароль.

То бишь, обычно регистрации пишутся по следующей схеме:

Игрок подключается к серверу
Сервер посылает запрос в базу данных на поиск аккаунта с ником игрока
Если аккаунт не найден - регистрация. Если найден - загрузка пароля и авторизация
После успешной авторизации посылается запрос на загрузку аккаунта


А в случае с сохранённым кэшем она будет выглядеть так:

Игрок подключается к серверу
Сервер посылает запрос в базу данных на поиск аккаунта с ником
Если аккаунт найден - загрузка пароля, сохранение кэша и авторизация
После успешной авторизации продолжается работа с сохранённым кэшем, из которого загружается аккаунт


Вот и всё.

danya9877
20.03.2017, 01:30
И все-таки, по поводу последнего.
Я имел ввиду что я в самом начале когда подгружаются все данные, какие-то я не записываю в переменные (как Reg-IP), а оставляю в кэше пока игрок не выйдет с сервера. Или так лучше не делать?)

DeimoS
20.03.2017, 11:34
И все-таки, по поводу последнего.
Я имел ввиду что я в самом начале когда подгружаются все данные, какие-то я не записываю в переменные (как Reg-IP), а оставляю в кэше пока игрок не выйдет с сервера. Или так лучше не делать?)

Ну либо ты раз их выгружаешь из кэша и всё (обычная реализация), либо ты каждый раз вынужден переключаться на кэш игрока, извлекать из него данные в переменную и только потом её использовать (твой вариант). Сам как думаешь? :)

123
25.03.2017, 14:33
Ты не совсем правильно понял пример в wiki.
Там при входе на сервер происходит запрос в базу данных с выборкой всей информации о игроке. После этого в массив загружается исключительно пароль (для дальнейшей сверки с тем, что вводит игрок) и ничего более, а сам кэш сохраняется и в массив "Player[playerid][Data]" записывается ID кэша.
Далее, если игрок вводит верный пароль, происходит обращение к записанному кэшу по его ID и последующая загрузка данных их кэша (точно такими же функциями, как и, например, в mysql_tquery) и кэш удаляется. Если игрок вышел и кэш всё ещё существует (например, он отказался от ввода пароля и вышел) - так же удаление.
Сделано это для того, чтоб не посылать повторный запрос в базу данных для загрузки аккаунта в случае, если игрок ввёл верный пароль.

То бишь, обычно регистрации пишутся по следующей схеме:

Игрок подключается к серверу
Сервер посылает запрос в базу данных на поиск аккаунта с ником игрока
Если аккаунт не найден - регистрация. Если найден - загрузка пароля и авторизация
После успешной авторизации посылается запрос на загрузку аккаунта


А в случае с сохранённым кэшем она будет выглядеть так:

Игрок подключается к серверу
Сервер посылает запрос в базу данных на поиск аккаунта с ником
Если аккаунт найден - загрузка пароля, сохранение кэша и авторизация
После успешной авторизации продолжается работа с сохранённым кэшем, из которого загружается аккаунт


Вот и всё.

Ну и как оно, лучше будет реализовать авторизацию именно таким образом?

DeimoS
25.03.2017, 14:42
Ну и как оно, лучше будет реализовать авторизацию именно таким образом?

Логично, что с сохранением кэша, ибо всего 1 запрос отправляется. Но это не значит, что "обычный" вариант неприемлем.

123
25.03.2017, 14:45
Логично, что с сохранением кэша, ибо всего 1 запрос отправляется. Но это не значит, что "обычный" вариант неприемлем.

А после авторизации игрока, кэш следует удалять? И перед удалением, нужно использовать cache_unset_active ?

DeimoS
25.03.2017, 14:57
А после авторизации игрока, кэш следует удалять?

Да. И после отключения игрока от сервера, проверяя то, существует ли кэш (cache_is_valid)


И перед удалением, нужно использовать cache_unset_active ?

Нет. Ты же удаляешь его по ID. А cache_unset_active нужна для того, чтоб функции работы с кэшем, типа cache_get_field_content_int (все, в которых нет параметра, указывающего на ID кэша), понимали с каким кэшем идёт работа

- - - Добавлено - - -

В общем, скачай отсюда (https://github.com/pBlueG/SA-MP-MySQL/releases) исходники плагина, найди там папку "example_scripts" и в ней будет скрипт "login_system-cache.pwn". Самый наглядный пример из всех, что есть

_lizard
26.03.2017, 22:10
В общем, скачай отсюда (https://github.com/pBlueG/SA-MP-MySQL/releases) исходники плагина, найди там папку "example_scripts" и в ней будет скрипт "login_system-cache.pwn". Самый наглядный пример из всех, что есть

Ради интереса заглянул я в эти примеры скриптов и увидел там это:


mysql_format(g_SQL, query, sizeof query, "SELECT * FROM `players` WHERE `username` = '%e' LIMIT 1", Player[playerid][Name]);


Разве mysql_format() не защищает от инъекций без спецификатора '%e'?

DeimoS
26.03.2017, 22:23
Ради интереса заглянул я в эти примеры скриптов и увидел там это:


mysql_format(g_SQL, query, sizeof query, "SELECT * FROM `players` WHERE `username` = '%e' LIMIT 1", Player[playerid][Name]);


Разве mysql_format() не защищает от инъекций без спецификатора '%e'?

Эмм, нет. С чего ты взял?
Наоборот, спецификатор "%e" есть только в mysql_format. Для того эта функция, тащемта, и сделана (не считая возможности пользовательские привилегии изменять, что никто не делает особо).