PDA

Просмотр полной версии : [Вопрос] Что означают эти логи в MySQL?



annas2001
17.08.2019, 12:51
В очередной раз обращаюсь сюда, либо не умею гуглить, либо у меня одной такие ошибки.

Залила сервер на хостинг, поменяла плагин MySQL под систему Debian, вроде все работает, кроме MySQL. Не запускается авторизация, в логах пишет это:

[08/17/19 11:47:48] [INFO] changed log level from 'warning, error' to 'debug, info, warning, error'
[08/17/19 11:47:48] [DEBUG] CThreadedConnection::WorkerFunc(this=0xf4a90008, connection=0xf4a90008)
[08/17/19 11:47:48] [DEBUG] CThreadedConnection::WorkerFunc(this=0xf420e008, connection=0xf420e008)
[08/17/19 11:47:48] [DEBUG] CThreadedConnection::WorkerFunc(this=0xf5312008, connection=0xf5312008)

DeimoS
17.08.2019, 13:08
[08/17/19 11:47:48] [INFO] changed log level from 'warning, error' to 'debug, info, warning, error'
Это просто сообщение о том, какой уровень логирования включен (ну тут говорится, что уровень логирования переключён с "отображать в логах только предупреждения и ошибки" на "отображать всю информацию").
А дальше просто попытки соединения.


Подключи crashdetect, удали server_log.txt, запусти сервер и после запуска скинь содержимое server_log.txt от начала и до конца.

UPD: Перенёс тему в раздел с ошибками.

annas2001
17.08.2019, 17:40
Это просто сообщение о том, какой уровень логирования включен (ну тут говорится, что уровень логирования переключён с "отображать в логах только предупреждения и ошибки" на "отображать всю информацию").
А дальше просто попытки соединения.


Подключи crashdetect, удали server_log.txt, запусти сервер и после запуска скинь содержимое server_log.txt от начала и до конца.

UPD: Перенёс тему в раздел с ошибками.

Не знаю почему, но после установки краш детекта у меня магическим образом все заработало..

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

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

Как исправить?

stock SavePlayerPos(playerid)
{
GetPlayerPos(playerid, spawn_info[playerid][x], spawn_info[playerid][y], spawn_info[playerid][z]);
GetPlayerFacingAngle(playerid, spawn_info[playerid][angle]);
spawn_info[playerid][interior] = GetPlayerInterior(playerid);
spawn_info[playerid][vw] = GetPlayerVirtualWorld(playerid);
new query[MAX_PLAYER_NAME + 50];
format(query, sizeof(query), "SELECT * FROM `positions` WHERE `name` = '%s'", account[playerid][name]);
new rows, Cache:result = mysql_query(connection_handle, query, true);
cache_get_row_count(rows);
if(rows)
{
new query_string[200];
format(query_string, sizeof(query_string), "UPDATE `positions` SET `x` = '%f', `y` = '%f', `z` = '%f', `angle` = '%f', `interior` = '%d', `vw` = '%d'",\
spawn_info[playerid][x],
spawn_info[playerid][y],
spawn_info[playerid][z],
spawn_info[playerid][angle],
spawn_info[playerid][interior],
spawn_info[playerid][vw]);
mysql_tquery(connection_handle, query_string, "", "");
}
else
{
new query_string[175 + MAX_PLAYER_NAME];
format(query_string, sizeof(query_string), "INSERT INTO `positions` (`name`, `x`, `y`, `z`, `angle`, `interior`, `vw`) VALUES ('%s', '%f', '%f', '%f', '%f', '%d', '%d')",\
account[playerid][name],
spawn_info[playerid][x],
spawn_info[playerid][y],
spawn_info[playerid][z],
spawn_info[playerid][angle],
spawn_info[playerid][interior],
spawn_info[playerid][vw]);
mysql_tquery(connection_handle, query_string, "", "");
}
cache_delete(result);
}

UnO
17.08.2019, 19:07
format(query_string, sizeof(query_string), "UPDATE `positions` SET `x` = '%f', `y` = '%f', `z` = '%f', `angle` = '%f', `interior` = '%d', `vw` = '%d'",\
spawn_info[playerid][x],
spawn_info[playerid][y],
spawn_info[playerid][z],
spawn_info[playerid][angle],
spawn_info[playerid][interior],
spawn_info[playerid][vw]);

-->>


format(query_string, sizeof(query_string), "UPDATE `positions` SET `x` = '%f', `y` = '%f', `z` = '%f', `angle` = '%f', `interior` = '%d', `vw` = '%d' WHERE name = '%s'",
spawn_info[playerid][x],
spawn_info[playerid][y],
spawn_info[playerid][z],
spawn_info[playerid][angle],
spawn_info[playerid][interior],
spawn_info[playerid][vw],
account[playerid][name]);

Outsider
17.08.2019, 19:48
У тебя будет еще масса подобных ошибок, если ты будешь каждый раз вручную составлять запросы. Это долго и всегда есть шанс ошибиться. В качестве альтернативы могу предложить Easy MySQL (https://forum.sa-mp.com/showthread.php?t=606930). Честно говоря первая попавшаяся либа, которую юзаю сам. Возможно есть другие и получше, но мне конкретно эта нравится возможностью переключиться на SQLite в любой момент просто переподключив инклюд.

DeimoS
17.08.2019, 20:18
Не знаю почему, но после установки краш детекта у меня магическим образом все заработало..

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

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

Как исправить?

stock SavePlayerPos(playerid)
{
GetPlayerPos(playerid, spawn_info[playerid][x], spawn_info[playerid][y], spawn_info[playerid][z]);
GetPlayerFacingAngle(playerid, spawn_info[playerid][angle]);
spawn_info[playerid][interior] = GetPlayerInterior(playerid);
spawn_info[playerid][vw] = GetPlayerVirtualWorld(playerid);
new query[MAX_PLAYER_NAME + 50];
format(query, sizeof(query), "SELECT * FROM `positions` WHERE `name` = '%s'", account[playerid][name]);
new rows, Cache:result = mysql_query(connection_handle, query, true);
cache_get_row_count(rows);
if(rows)
{
new query_string[200];
format(query_string, sizeof(query_string), "UPDATE `positions` SET `x` = '%f', `y` = '%f', `z` = '%f', `angle` = '%f', `interior` = '%d', `vw` = '%d'",\
spawn_info[playerid][x],
spawn_info[playerid][y],
spawn_info[playerid][z],
spawn_info[playerid][angle],
spawn_info[playerid][interior],
spawn_info[playerid][vw]);
mysql_tquery(connection_handle, query_string, "", "");
}
else
{
new query_string[175 + MAX_PLAYER_NAME];
format(query_string, sizeof(query_string), "INSERT INTO `positions` (`name`, `x`, `y`, `z`, `angle`, `interior`, `vw`) VALUES ('%s', '%f', '%f', '%f', '%f', '%d', '%d')",\
account[playerid][name],
spawn_info[playerid][x],
spawn_info[playerid][y],
spawn_info[playerid][z],
spawn_info[playerid][angle],
spawn_info[playerid][interior],
spawn_info[playerid][vw]);
mysql_tquery(connection_handle, query_string, "", "");
}
cache_delete(result);
}

Подобное лучше делать запросом "INSERT ... ON DUPLICATE KEY UPDATE (https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html)". Только тип таблицы (https://i.imgur.com/WXhJv2i.png) должен быть обязательно "MyISAM", а не "InnoDB".
Хотя вообще проще было хранить координаты вместе с аккаунтом, если у тебя ничего, кроме координат, интерьера и виртуального мира в таблице не хранится. Было бы меньше мороки с загрузкой/выгрузкой данных.


Ну а вообще проблема в том, что ты не добавила условие, которое бы ограничило запрос на обновление. В данном случае можно выгрузить ID строки из базы и потом сразу обновлять его.
stock SavePlayerPos(playerid)
{
GetPlayerPos(playerid, spawn_info[playerid][x], spawn_info[playerid][y], spawn_info[playerid][z]);
GetPlayerFacingAngle(playerid, spawn_info[playerid][angle]);
spawn_info[playerid][interior] = GetPlayerInterior(playerid);
spawn_info[playerid][vw] = GetPlayerVirtualWorld(playerid);
new query[MAX_PLAYER_NAME + 50];
format(query, sizeof(query), "SELECT id FROM positions WHERE name='%s'", account[playerid][name]);
new rows, Cache:result = mysql_query(connection_handle, query, true);
cache_get_row_count(rows);
if(rows)
{
new row_id;
cache_get_value_name_int(0, "id", row_id);
new query_string[200];
format(query_string, sizeof(query_string),
"UPDATE positions SET x=%f,y=%f,z=%f,angle=%f,interior=%d,vw=%d WHERE id=%d",\
spawn_info[playerid][x],
spawn_info[playerid][y],
spawn_info[playerid][z],
spawn_info[playerid][angle],
spawn_info[playerid][interior],
spawn_info[playerid][vw],
row_id);
mysql_tquery(connection_handle, query_string, "", "");
cache_delete(result);
}
else
{
new query_string[175 + MAX_PLAYER_NAME];
format(query_string, sizeof(query_string), "INSERT INTO positions(name,x,y,z,angle,interior,vw)VALUES('%s',%f,%f,%f,%f,%d,%d)",\
account[playerid][name],
spawn_info[playerid][x],
spawn_info[playerid][y],
spawn_info[playerid][z],
spawn_info[playerid][angle],
spawn_info[playerid][interior],
spawn_info[playerid][vw]);
mysql_tquery(connection_handle, query_string, "", "");
}
}
И да, ты зря всё подряд выделяешь апострофами. Имена столбцов/таблиц выделять обратным апострофом требуется только тогда, когда это самое имя соответствует одному из зарезервированных слов (https://dev.mysql.com/doc/refman/8.0/en/keywords.html#keywords-in-current-series). А в случае с обычными данными апострофами выделяются только строки (ну и, возможно, некоторые специфические типы данных). Во всех остальных случаях ты просто впустую тратишь память и время на запись дополнительных символов.

Так же cache_delete использовать нужно только если кэш был найден. Иначе в лог будет выдавать предупреждение о том, что не найден кэш для удаления (не критично, но зачем лишний флуд?)




format(query, sizeof(query), "SELECT * FROM `positions` WHERE `name` = '%s'", account[playerid][name]);
new rows, Cache:result = mysql_query(connection_handle, query, true);

А ещё, если требуется проверить наличие каких-либо данных в таблице, то лучше не все столбцы выгружать, а просто сказать MySQL вернуть определённое число/текст. Например, единицу:
new query[MAX_PLAYER_NAME + 50];
format(query, sizeof(query), "SELECT 1 FROM `positions` WHERE `name` = '%s' LIMIT 1", account[playerid][name]);
new rows, Cache:result = mysql_query(connection_handle, query, true);
cache_get_row_count(rows);
if(rows)
{
// Найдено
}
else
{
// Не найдено
}
А так же не забывай про "LIMIT 1", если тебе нужно выгрузить всего одну строку и, при этом, выборка происходит не по уникальному полю: например, если у тебя в условии запроса указано поле "id", которое в таблице имеет параметр "AUTO_INCREMENT", то указывать "LIMIT" не нужно. Или если для столбца "name" создать индекс, сделав его уникальным (чего без повода делать не стоит), то тоже "LIMIT" не будет требоваться, ибо MySQL сама поймёт, что результат может быть только 1. А вот в твоём текущем примере "LIMIT" будет нужен.
Иначе просто будет так, что MySQL, например, нашла нужный столбец самым первым, но если в таблице будет, допустим 10000 записей, MySQL продолжит проверять эти оставшиеся записи, так как ты не указала, что строка всего одна.




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


Эмм, а научиться работать с запросами не судьба? Там же достаточно знать основы, которые довольно элементарные. Конкретно для SA-MP, в первую очередь, достаточно прочесть о том, как составляются SELECT, UPDATE и DELETE-запросы. Всё остальное уже гуглежом находится легко.
Крайне странное предложение.
И да, этой библиотекой ты мало того, что кучу памяти тратишь, так ещё и по скорости будешь проигрывать обычным запросам из-за того, что каждая функция библиотеки содержит кучу своих внутренних проверок, подтягивающих вызов кучи других функций.

В общем, какая-то рубрика "вредные советы", не иначе.

Outsider
17.08.2019, 20:30
Во-первых, я веб девелопер...
Ну я не вижу ничего плохого в том, чтобы немного проиграть в скорости ради того, чтобы код выглядел красивее и читабельнее. Алсо, ничего не мешает написать библиотеку под свои нужды, но лично меня устраивают готовые решения, в данном случае по крайней мере.

DeimoS
17.08.2019, 20:40
Во-первых, я веб девелопер...
Ну я не вижу ничего плохого в том, чтобы немного проиграть в скорости ради того, чтобы код выглядел красивее и читабельнее. Алсо, ничего не мешает написать библиотеку под свои нужды, но лично меня устраивают готовые решения, в данном случае по крайней мере.

"Красивее и читабельнее" - крайне сомнительное утверждение, с учётом того, что функционал библиотеки имеет довольно специфический синтаксис для SA-MP.
И, опять же, даже если представить, что данная библиотека - это "красивее и читабельнее", то ради этой самой красоты ты и памяти тратишь кучу, и время на обработку функций библиотеки теряешь, и теряешь в гибкости настройки запросов (библиотека справится с банальной выгрузкой/созданием/сохранением. Но составить какие-то более-менее сложные запросы уже будет гораздо проблематичнее, если вообще возможно). Как-то слишком много потерь ради "красивее и читабельнее".

Ну и да - это тот же самый ORM, что прикручен к плагину, только реализованный на Pawn и более кривой. Собственно, моё мнение на этот счёт всё то же - совет, скорее, вредный, чем полезный.
Если нет желания разбираться в MySQL, то лучше продолжать сидеть на файлах, ибо неумелыми действиями крайне легко слить в трубу всё преимущество MySQL.

Outsider
17.08.2019, 21:38
"Красивее и читабельнее" - крайне сомнительное утверждение, с учётом того, что функционал библиотеки имеет довольно специфический синтаксис для SA-MP.
И, опять же, даже если представить, что данная библиотека - это "красивее и читабельнее", то ради этой самой красоты ты и памяти тратишь кучу, и время на обработку функций библиотеки теряешь, и теряешь в гибкости настройки запросов (библиотека справится с банальной выгрузкой/созданием/сохранением. Но составить какие-то более-менее сложные запросы уже будет гораздо проблематичнее, если вообще возможно). Как-то слишком много потерь ради "красивее и читабельнее".

Ну и да - это тот же самый ORM, что прикручен к плагину, только реализованный на Pawn и более кривой. Собственно, моё мнение на этот счёт всё то же - совет, скорее, вредный, чем полезный.
Если нет желания разбираться в MySQL, то лучше продолжать сидеть на файлах, ибо неумелыми действиями крайне легко слить в трубу всё преимущество MySQL.

Да я умею составлять запросы к базе, если там есть что уметь. Просто зачем мне это, если есть либа с которой я могу этого не делать? Если в процессе использования библиотеки окажется, что мне её мало / я действительно что-то теряю, юзая её, то не составит труда написать свой аналог попроще под свои нужды. Искренне не понимаю в чем проблема.

Впрочем, ты меня в данном вопросе не переубедишь пока я сам не наступлю на грабли. Это немного специфичнее, чем какие-то типичные (или не очень) ошибки в pawn где я 100% к тебе прислушаюсь, в силу неопытности. Так что наверное весь оффтоп зря. Хотя, возможно, ты переубедишь ТСа. :)