MySql пояснение.

Jafa

Участник
Сообщения
159
Реакции
3
Здравствуйте, можно ли как-то написать функцию которая будет сама проверять есть ли ключь в базе и если есть то Делать UPDATE если нет то делать INSERT ... проще говоря нужно чтоб MySql работала бы как KeyValve .. неудобаство MySql в том что нужно сначала делать SELECT (проверять есть или там ключь и только потом делать UPDATE или INSERT) ... можно ли как-то это упростить? Т.к я не всегда могу знать есть ли там Ключь или нет... Надеюсь в вас не запутал своим вопросом))
 

The Night Fury

Участник
Сообщения
1,300
Реакции
1,395
MySQL :: MySQL 5.7 Reference Manual :: 14.2.8 REPLACE Syntax

Не нужно тянуть SELECT. Или можно использовать ON DUPLICATE. Только с этим возвращаясь к проблеме с

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

Jafa

Участник
Сообщения
159
Реакции
3
MySQL :: MySQL 5.7 Reference Manual :: 14.2.8 REPLACE Syntax

Не нужно тянуть SELECT. Или можно использовать ON DUPLICATE. Только с этим возвращаясь к проблеме с


Значит хреново сделана база. Ключи либо должны быть, либо не должны.
ну вот в качестве ключа стимид игрока.. нужно же как-то проверить есть ли он в базе или нет.. или как лучше устроить базу?
--- Добавлено позже ---
Давайте попробую объяснить на примере. Я хочу создать крайне точную базу данных игроков. Нужно чтоб даже в случае краша сервера не одна смерти, ни одно убийство не было упущено!

Предложите какая должны быть структура БД, чтоб даже в случае краша убйиства игроком перед крашем или смерть игрока не потерялась.. и опять же нужно-же как-то проверять есть ли игрок в базе или нет.. а от этого зависит что мы должны делать INSERT или UPDATE ... пожалуйста помогите кто на опыте =) STEAM_ID - Убийства - Смерти.
 
Последнее редактирование:

iSe7en

Участник
Сообщения
209
Реакции
111
ну вот в качестве ключа стимид игрока.. нужно же как-то проверить есть ли он в базе или нет.. или как лучше устроить базу?
--- Добавлено позже ---
Давайте попробую объяснить на примере. Я хочу создать крайне точную базу данных игроков. Нужно чтоб даже в случае краша сервера не одна смерти, ни одно убийство не было упущено!

Предложите какая должны быть структура БД, чтоб даже в случае краша убйиства игроком перед крашем или смерть игрока не потерялась.. и опять же нужно-же как-то проверять есть ли игрок в базе или нет.. а от этого зависит что мы должны делать INSERT или UPDATE ... пожалуйста помогите кто на опыте =) STEAM_ID - Убийства - Смерти.
C-подобный:
INSERT INTO ___  VALUES ___ ON DUPLICATE KEY UPDATE ___
 

iSe7en

Участник
Сообщения
209
Реакции
111
вот честно не понял)) можно на примере и с описанием?

В этом примере steamid - это первичный ключ таблицы players. Если в бд есть игрок с таким steamid, то выполнится запрос на обновление его ip и name. Если нет, то добавится запись с steamid, ip, name.
C-подобный:
INSERT INTO players (steamid, ip, name) VALUES ('STEAM_1:0:27456405', '127.0.0.1', 'Se7en') ON DUPLICATE KEY UPDATE ip = VALUES(ip),  name = VALUES(name)
 

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
@Jafa, если ты хочешь, чтобы ничего не терялось, то придётся делать запрос к бд почти при каждом событии, а это не есть хорошо.
Посмотри здесь Ядро плагина - dPInfo как я использую этот запрос.
В таблице mysql steamid должен быть ключом.
 

Jafa

Участник
Сообщения
159
Реакции
3
@Jafa, если ты хочешь, чтобы ничего не терялось, то придётся делать запрос к бд почти при каждом событии, а это не есть хорошо.
Посмотри здесь Ядро плагина - dPInfo как я использую этот запрос.
В таблице mysql steamid должен быть ключом.
на сколько я понял грубо говоря... обычно с базой MySql работают примерно так. Получают данные - записывают в массив и когда игрок выходит записываем данные из массивов в базу MySql ?

И еще 1 вопрос Если сервер крашнется 100% что-то да потеряется или можно как-то себя обезопасить?
--- Добавлено позже ---
Как лучше: Создать отдельную таблицу для Игрока в которой будет записаны все его данные которые нужны (сколько будет игроков столько будет и таблиц) или Создать таблица Players с ключами (SteamID) в каждом поле принадлежащем этому ключу будут записаны нужные данные?

Какие есть плюсы и минусы у этих 2 структур?
 
Последнее редактирование:

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
на сколько я понял грубо говоря... обычно с базой MySql работают примерно так. Получают данные - записывают в массив и когда игрок выходит записываем данные из массивов в базу MySql ?
Именно так. Но вот та проблема, которую ты хочешь обойти - потеря данных. Представь, что ты получил данные игроки, записал их в массив. И как игрок выйдет, ты хочешь отправить данные из массива в mysql. Допустим, что будут какие-то внешние события, которые могут повлиять на этот алгоритм, например крашнулся игровой сервер, или вовсе сервер mysql перестал быть доступным. Что будет в этом случае?
Крашнулся сервер - значит, что событие выхода игрока не будет вызвано, а это значит, что всё, чего достиг игрок во время игры (после того, как его данные были записаны в массив), будет утеряно. В этом случае тебе стоит отправлять данные на mysql всегда, когда ты изменяешь эти данные в массиве (игрок убил кого-то - записал это в массив(переменную или хз где ты хранить это будешь) и отправил на mysql, но такое решение не есть хорошо.

Посреди работы сервер mysql стал недоступен - допустим у игрока в mysql записано 100 уровень. Игрок подключается, игровой сервер пытается получить данные с mysql, но он не отвечает, следовательно все переменные игрока (массив) равны 0 (уровень = 0), т.к. новые данные не были получены. Допустим, что посреди игры сервер mysql заработал, и игрок вышел, а значит, все данные из его массива должны быть отправлены на mysql, а т.к. его переменные равны 0, в mysql будет отправлены нулевые данные, то бишь все его данные обнулятся, а уровень будет равен 0.
 

sBorislav

Взломал GameCMS 3.411 - 27.02.18
Сообщения
196
Реакции
177
А смысл создавать несколько таблиц? MySql как и любая база и таблица это связка ключ - значение и работает она именно так. Смысл создавать таблицу для игрока, если все значения все равно уместятся в одну строчку. Ты просто будешь тратить лишние байты свободного места на таблицы, структура которых все равно будет одинаковой. Так никто не делает и делать не будет
 

Jafa

Участник
Сообщения
159
Реакции
3
В этом случае тебе стоит отправлять данные на mysql всегда, когда ты изменяешь эти данные в массиве (игрок убил кого-то - записал это в массив(переменную или хз где ты хранить это будешь) и отправил на mysql, но такое решение не есть хорошо.
получается и так плохо и так плохо... остается выбирать меньшее из зол?
 

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
@Jafa, почему, если включить голову и хорошенько подумать, то можно найти оптимальное решение для обоих вариантов. Я всегда придерживаюсь варианта загружать при входе и сохранять при выходе.
 

Jafa

Участник
Сообщения
159
Реакции
3
стоит ли задумывать о чистке базы от игроков? Если игрок давно не заходил то его не мешало бы удалить из базы? Т.е получается нужно запустить цыкл по всем ключам (стимид) табицы и удалить те которые не юзались более месяца ... так можно сдлеать отправив 1 запрос? или нужно посылать запросы в цыкле?
 

iSe7en

Участник
Сообщения
209
Реакции
111
стоит ли задумывать о чистке базы от игроков? Если игрок давно не заходил то его не мешало бы удалить из базы? Т.е получается нужно запустить цыкл по всем ключам (стимид) табицы и удалить те которые не юзались более месяца ... так можно сдлеать отправив 1 запрос? или нужно посылать запросы в цыкле?
Записывай дату последнего обновления в строку с игроком и потом удаляй старые одним запросом
 
  • Мне нравится
Реакции: Jafa

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
DELETE FROM 'users' WHERE date < 1487610084. Удалит записи 30 дневной давности. Правда тебе надо будет в date записывать время последнего входа игрока. В SourcePawn функция GetTime(), которая возвращает unix time в секундах.
 
  • Мне нравится
Реакции: Jafa

iSe7en

Участник
Сообщения
209
Реакции
111
если вас не затруднит дайте пример такого удаления.
Добавляешь столбец updated и записываешь туда текущее время в unixtime при обновлении данных.
Что бы удалить неактивных игроков, достаточно будет сделать запрос
DELETE players WHERE updated < 1487437262

Число 1487437262 это 1490029262 ( текущее время в unixtime) - 2592000 (30 дней в секундах) = Текущее время - 30 дней.
То бишь удалить игроков, у которых дата обновления была больше 30 дней назад.
 
  • Мне нравится
Реакции: Jafa

Jafa

Участник
Сообщения
159
Реакции
3
Еще один небольшой пример. Скажите что произойдет если я отправлю запрос в базу а через 0.1 сек сервер упадет т.е перед падением сервер отправил запрос в MySql но не успел получить ответ... (колбек) - в базе данных изменение по идее будет записано?
--- Добавлено позже ---
И еще одно если я послал 2 запроса с разницей в 0.05 секунд есть вероятность что запрос которые отправле последним придет первее? (просто нужно знать для саморазвития и большего понимания)
--- Добавлено позже ---
И не отходя от кассы еще 3 вопрос я могу создать базу такого вида? И как (если можно на примере получение\записи данных) =)
--- Добавлено позже ---
--- Добавлено позже ---
SQL_EscapeString - подскажите пожалуйста для чего она нужна? встречал пару раз.. но на sm по описанию не совсем догнал..
 

Вложения

  • images.png
    images.png
    887 байт · Просмотры: 9
Последнее редактирование:

Primo

типа серьёзный тип
Сообщения
1,532
Реакции
759
Еще один небольшой пример. Скажите что произойдет если я отправлю запрос в базу а через 0.1 сек сервер упадет т.е перед падением сервер отправил запрос в MySql но не успел получить ответ... (колбек) - в базе данных изменение по идее будет записано?
Смотря какой запрос, если селективный, то никаких изменений не будет, ведь ты их не делаешь. Если запрос изменяет таблицу, то вполне должен успеть. Лёгкие запросы выполняются в сотых, а то и тысячных секундах.

И не отходя от кассы еще 3 вопрос я могу создать базу такого вида? И как (если можно на примере получение\записи данных) =)
Можно, если, например, использовать json, но я не уверен, поддерживается и существует ли он на sm. Но, опять же, это не имеет смысла, т.к. sm не умеет получать массив данных в колбеке, нужно записывать каждое значение в отдельную переменную. Поэтому придётся старым дедовским способом в каждую ячейку таблицы записывать данные, внутри ячейки массив не сделаешь (хотя конечно же можно записывать строку с символом для разбивки на массив, а в плагине потом разбивать, но это муторно, и не всегда необходимо).

SQL_EscapeString - подскажите пожалуйста для чего она нужна? встречал пару раз.. но на sm по описанию не совсем догнал..
Это чтобы запрос не сломать строкой. Какой-нибудь игрок поставил в нике ' (кавычку), а ты решил его сохранить, и запрос не проходит, т.к. выдаст ошибку об неверном синтаксисе, т.к. была найдена лишняя кавычка. Вот эта функция решает эту проблему.
 
Сверху Снизу