Помогите Задержка MySQL в плагинах

Статус
Закрыто для дальнейших ответов.

Bezobrazie

Активный участник
Пользователь
Баллы
46
Имя в Minecraft
MySoulIsCry
Начал ковырять базы данных и понял 1 проблему которая как мне кажется всплывет.
Когда подключаюсь к базе на это уходит время и даже если я буду подключатся к ней в асинк потоке чтобы серв не зависал то все равно мне кажется будет путаница с данными.
Допустим я пишу плагин на кейсы, в базе будут хранится игроки и какие кейсы ему доступны. При открытии кейса у игрока в базе уменьшается число кейсов на 1 так как он его открыл, но если есть задержка то есть вариант того что игрок очень быстро откроет второй кейс и число не успеет обновится в бд и тем самым он дюпнет кейс. Я понимаю что я не понятно объяснил в чем мой вопрос но вообще хз как сформулировать правильно. Но прошу объяснить как это правильно работает и вообще будут ли такие так скажем дюпы или у меня просто крыша едет.
Я начал изучать SQL 30 минут назад не кидайтесь помидорами.:nerd:
Вот мои тайминги если интересно.(бд не локальная)
Код:
Идет подключение к базе данных...
Вы подключились к базе данных за 780ms
Вы создали стейтмент и таблицу за 104ms
 
Последнее редактирование:
не знаю как люди это нормально делают, могу предложить свой вариант.
открываешь транзакцию
апдейтишь число кейсов set case_count = case_count - 1 where case_count > 0
смотришь апдейтнулось ли (оно возвращает число обновленных строк)
(вместо этого можно через select for update выбрать число кейсов и потом апдейтить уже без проверок)
выдаешь кейс
коммитишь транзакцию

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

а вообще звучит как задача о распределенной транзакции (нужно атомарно выдать кейс в игре и обновить запись в базе) и она хз как решается.
логов побольше добавь на всякий случай, чтобы если чел пожалуется, можно было понять выдался кейс или нет
 
Ты не создавай коннекты на каждый запрос, а держи один на все, тогда все будет летать, если все правильно сделано. И, конечно, не стоит забывать про кеширование частоиспользуемых данных.
Кешируй кейсы в мапе (загружай их при включении плагина), при его открытии меняешь в кешированном объекте число кейсов и все, и сохраняешь в бд, чтобы внезапных откатов не было на случай аварийной остановки сервера.
Такая же штука и с игроками. При входе игрока кешируешь его данные кейсов, при выходе сохраняешь и не забываешь удалять его из мапы
 
Последнее редактирование:
не знаю как люди это нормально делают, могу предложить свой вариант.
открываешь транзакцию
апдейтишь число кейсов set case_count = case_count - 1 where case_count > 0
смотришь апдейтнулось ли (оно возвращает число обновленных строк)
(вместо этого можно через select for update выбрать число кейсов и потом апдейтить уже без проверок)
выдаешь кейс
коммитишь транзакцию

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

а вообще звучит как задача о распределенной транзакции (нужно атомарно выдать кейс в игре и обновить запись в базе) и она хз как решается.
логов побольше добавь на всякий случай, чтобы если чел пожалуется, можно было понять выдался кейс или нет
А допустим если мне нужно отменить ивент какой либо допустим получение урона. а отменять урон или нет находится в бд я ж не смогу отменить ивент через 104ms после его вызова. что делать тогда?
 
Ты не создавай коннекты на каждый запрос, а держи один на все, тогда все будет летать, если все правильно сделано. И, конечно, не стоит забывать про кеширование частоиспользуемых данных.
Кешируй кейсы в мапе (загружай их при включении плагина), при его открытии меняешь в объекте кейса число кейсов и все, и сохраняешь в бд, чтобы внезапных откатов не было на случай аварийной остановки сервера.
Такая же штука и с игроками. При входе игрока кешируешь его данные кейсов, при выходе сохраняешь.
хорошая идея сохранять данные в бд при остановке сервера или с задержкой каждые 5 минут. а сами данные хранить в памяти. и загружать данные при включении. Наверное этим и буду пользоваться максимально просто и практично.
 
хорошая идея сохранять данные в бд при остановке сервера или с задержкой каждые 5 минут. а сами данные хранить в памяти. и загружать данные при включении. Наверное этим и буду пользоваться максимально просто и практично.
Подгружай данные самого плагина при включении. Данные игроков можно подгружать на AsyncPlayerPreLoginEvent без вызова шедулера. Сохранять следует скорей при каждом изменении.
 
хорошая идея сохранять данные в бд при остановке сервера или с задержкой каждые 5 минут. а сами данные хранить в памяти. и загружать данные при включении. Наверное этим и буду пользоваться максимально просто и практично.
так задумался не много ли будет жрать такой плагин ОЗУ допустим у меня 5к строчек кода и много данных для 1 игрока и хранить их в ОЗУ не затратно ли будет?
 
так задумался не много ли будет жрать такой плагин ОЗУ допустим у меня 5к строчек кода и много данных для 1 игрока и хранить их в ОЗУ не затратно ли будет?
что можно хранить в 5к строчках на игрока, запись идет по одному символу на строку?
в базе будут хранится игроки и какие кейсы ему доступны
 
что можно хранить в 5к строчках на игрока, запись идет по одному символу на строку?
назвал просто для примера самое большое число но такто много что можно хранить для 1 игрока (если что плагин на кейсы был выдуман чисто для примера)
 
назвал просто для примера самое большое число но такто много что можно хранить для 1 игрока (если что плагин на кейсы был выдуман чисто для примера)
Если это не нужно юзать на сайте, то можно записать PersistentDataContainer в Player.
 
Если это не нужно юзать на сайте, то можно записать PersistentDataContainer в Player.
нет просто начал ковырять из за того что на 2х серверах нужно иметь 1 и теже данные а с помощью конфигов так не сделаешь + лучше хранить данные в бд хоть и локальной, удобнее + надо же прогрессировать
 
назвал просто для примера самое большое число но такто много что можно хранить для 1 игрока (если что плагин на кейсы был выдуман чисто для примера)
Можно разделить информацию.
Все что связано с донатом, сделать прямое обновление данных с базы. Если делать проверку перед каждым открытием то дюпа не будет, к тому же можно просто поставить задержку на клик по кейсу например в 1 секунду (Запрос к базе с интервалом в одну секунду погоду не испортит)
А какие то игровые действия, уровень, ачивки, и другую лабуду загружать в объект и иногда выгружать в базу, чтобы не было серьезных потерь при несанкционированном краше. К тому же если брать личную статистику то 4к игроков в среднем занимают 15к строк. А подгруженных в онлайне будет ну максимум 200)
 
Храни в хашмапе допустим данные, а когда игрок выходит, либо каждые 30 минут выгружай в бд единым запросом. Соответственно данные в хашмапу загружай когда игрок входит. AsyncPlayerPreLoginEvent - как написали выше, не особо эффективен, если говорить про оптимизацию, ибо игрока может выкинуть, а запрос в бд уже отправился, лучше всего при PlayerJoinEvent, но если тебе данные сразу надо выводить допустим в скорбоард, это тоже косяк.
 
Храни в хашмапе допустим данные, а когда игрок выходит, либо каждые 30 минут выгружай в бд единым запросом. Соответственно данные в хашмапу загружай когда игрок входит. AsyncPlayerPreLoginEvent - как написали выше, не особо эффективен, если говорить про оптимизацию, ибо игрока может выкинуть, а запрос в бд уже отправился, лучше всего при PlayerJoinEvent, но если тебе данные сразу надо выводить допустим в скорбоард, это тоже косяк.
Да никакого касяка, до PlayerJoinEvent скорборд игрок не увидит.
 
Запрос к базе с интервалом в одну секунду погоду не испортит
Представим, что мускл отвалился. Вот просто упал и всё. Ваши действия?

Я бы ждал ответа от базы на каждый запрос и потом думал, что дальше делать. Разумеется, всё это в асинк.
При исправном коннекте и правильных запросах отрабатываться будет быстро и сервер не заметит задержку.
Зато я гарантированно получу корректные данные.
 
нет просто начал ковырять из за того что на 2х серверах нужно иметь 1 и теже данные а с помощью конфигов так не сделаешь + лучше хранить данные в бд хоть и локальной, удобнее + надо же прогрессировать
Ну спорный вопрос, через банжиконфиг можно синхронизировать.
 
Статус
Закрыто для дальнейших ответов.
Назад
Верх