Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

UoKit.com Форумы _ Sphere Server 0.56 - Sphere X _ mysql

Автор: Famous 20.5.2017, 1:07

всем привет.

хочу поинтересоваться, как лучше обновлять записи в таблице?
то есть, делать это всегда когда игрок заходит или лучше раз в 24 часа ?
когда обновляешь запись в базе, нужно обязательно писать db.close или это не стоит?

Автор: Reality Audit 16.7.2017, 15:07

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


Автор: Llirik 16.7.2017, 18:59

Смотря, что ты собираешься делать. Если TOP, то, есть смысл обновлять раз в 1-2 часа (через столб TIMERF) и проверкой на (!<account.block>). А то прикинь какой-нибудь GM забанит игрока и он в топе так и останется пока ты сам не заметишь, и не вытрешь его сам руками или удалит... Не всегда удобно т.к. лучше автомат.

Автор: Famous 17.7.2017, 8:46

Цитата(Llirik @ 16.7.2017, 18:59) *

Смотря, что ты собираешься делать. Если TOP, то, есть смысл обновлять раз в 1-2 часа (через столб TIMERF) и проверкой на (!<account.block>). А то прикинь какой-нибудь GM забанит игрока и он в топе так и останется пока ты сам не заметишь, и не вытрешь его сам руками или удалит... Не всегда удобно т.к. лучше автомат.



Спасибо:)

Автор: Aimed 17.7.2017, 11:38

Если Connect делаешь то и Close всегда после выполнения запросов.

Для остальных вопросов не ясны требования.

Можно хоть каждую секунду, особенно если это все асинхронно выполняется.

Автор: Famous 18.7.2017, 20:46

при запуске db.connect и все, а потом уже команды для записи в базу.
при этом закрывать dc.close не нужно, верно ?

Автор: Juzzver 19.7.2017, 11:04

Цитата
при запуске db.connect и все, а потом уже команды для записи в базу.
при этом закрывать dc.close не нужно, верно ?

Открыл коннект, поработал с базой, закрыл коннект. Так нужно.

Автор: Aimed 19.7.2017, 11:56

Цитата(Famous @ 18.7.2017, 19:46) *

при запуске db.connect и все, а потом уже команды для записи в базу.
при этом закрывать dc.close не нужно, верно ?


И каждый раз заного будешь открывать новые сессии не закрывая старые.
Это по твоему норм?

Автор: Reality Audit 19.7.2017, 18:56

Смотря какой лимит пула конекций базы. Ребутить базу для того чтобы они закрылись - верный дедовский метод biggrin.gif
Открыл - поработал - закрыл.

Автор: Famous 20.7.2017, 10:26

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

как лучше сделать топ500 ?

Автор: Aimed 20.7.2017, 15:53

Цитата(Famous @ 20.7.2017, 9:26) *

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

как лучше сделать топ500 ?


Лучше делать такое в режиме live, когда у тебя при каждом обновлении атрибутов, которые нужны для топа будет обновляться таблица в базе. Допустим если у тебя даётся опыт за монстров и ты хочешь сделать топ500 игроков по накопленному опыту. У тебя при получении опыта каждый раз будет обновляться таблица в базе. Разумеется что делать все это надо асинхронно через AQUERY/AEXECUTE или как там в сферах.

Когда человек заходит на сайт, ты уже просто через SQL запрашиваешь данные используя order by и limit 500.

Можно так-же делать раз в х времени по таймеру/при старте сервера, проходиться по всем персонажам, соберать данные и записывать в таблицу в базе. Это хоть и будет выполняться реже, но будет нагружать сервер сильнее и возможно даже создавать лаги ( смотря сколько у тебя данных в памяти сервера ).

Автор: Juzzver 20.7.2017, 15:56

Цитата
ну папример топ500
всегда открыт коннект и когда игрок заходит в игру, идет записать в базу данных и после этого все равно соединение остается открытым.

как лучше сделать топ500 ?

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

Если ты заходишь в туалет, чтобы нагадить к примеру, но при этом не смываешь, то спустя время пулл унитаза будет переполнен, понимаешь?) Так и с подключением к БД надо поступать:
Цитата
Открыл коннект, поработал с базой, закрыл коннект. Так нужно.

Автор: Famous 20.7.2017, 17:53

Понял:) спасибо
У меня в данном случае 5 таблиц и обновляются при заходи в игре и всенда коннект открыт. Как воо поступить?

Или как вариант собирать сейвы а потом отдельно на компе записывать все в базу?smile.gif

Автор: Aimed 20.7.2017, 20:21

И что же ты понял если ты задал тот же самый вопрос?

Зачем шариться по сейвам? Во первых для этого прийдется делать отдельную программу которая будет полностью сжирать как минимум 1 поток распарсивая твой сейв, во вторых писать парсер для сейвов и в третьих гораздо легче делать обновление/новую запись в базе при действии игрока на сервере и иметь обновление топа в режиме live.

Автор: Famous 20.7.2017, 21:00

Например, при онлаин 50+ игрок зашел в игру (обновили/добавили) и сразу же закрыли соединение, так будет правильно ?

Автор: Aimed 20.7.2017, 21:56

Цитата(Famous @ 20.7.2017, 20:00) *

Например, при онлаин 50+ игрок зашел в игру (обновили/добавили) и сразу же закрыли соединение, так будет правильно ?


Жесть)
Да, так будет правильно.

Автор: Famous 20.7.2017, 22:57

пасибо smile.gif

Автор: Llirik 20.7.2017, 23:12

Приведите пример AQUERY/AEXECUTE!

Автор: Aimed 20.7.2017, 23:57

Цитата(Llirik @ 20.7.2017, 22:12) *

Приведите пример AQUERY/AEXECUTE!


У тебя проблемы с навигацией на SphereWiki?
http://wiki.spherecommunity.net/index.php?title=AQUERY
http://wiki.spherecommunity.net/index.php?title=AEXECUTE

Примеры внизу каждой страници по ссылке

Автор: Reality Audit 21.7.2017, 20:10

Пиво @Juzzver`y
Открытие коннекции, сбор атрибутов, запись в базу и закрытие коннекции - относительно недорогие операции. Ты их не заметишь, даже если постоянно будет заходить и выходить 50 игроков. С оговоркой что ты не собираешь стопицот аттрибутов - тогда парсинг свежего сейва будет оптимальнее.

Для сравнения - в свое время я отключал сон регионов и писал в базу статистику действий АИ и запись шла на каждый ивент, плюс одни мобы воевали с другими - это спокойно шло в фоне, за исключением ряда ситуаций.

Автор: Soteric 22.7.2017, 5:18

В сфере есть пул коннектов? Или на каждый запрос открывается/закрывается физически новое подключение?

Автор: Aimed 22.7.2017, 5:38

Цитата(Reality Audit @ 21.7.2017, 19:10) *

Пиво @Juzzver`y
Открытие коннекции, сбор атрибутов, запись в базу и закрытие коннекции - относительно недорогие операции. Ты их не заметишь, даже если постоянно будет заходить и выходить 50 игроков. С оговоркой что ты не собираешь стопицот аттрибутов - тогда парсинг свежего сейва будет оптимальнее.

Для сравнения - в свое время я отключал сон регионов и писал в базу статистику действий АИ и запись шла на каждый ивент, плюс одни мобы воевали с другими - это спокойно шло в фоне, за исключением ряда ситуаций.


А если на протяжении нескольких часов никто не будет заходить/выходить?
Да и не сильно это логично, собирать атрибуты со всех, когда кто-то заходит.

Автор: Reality Audit 22.7.2017, 11:08

От задачи зависит wacko.gif

@Soteric у базы есть

Автор: Aimed 22.7.2017, 22:53

Цитата(Reality Audit @ 22.7.2017, 10:08) *

От задачи зависит wacko.gif

@Soteric у базы есть


Гипотетическая задача была дана, - сделать топ500. Дальше можно самому додумать.

Цитата(Soteric @ 22.7.2017, 4:18) *

В сфере есть пул коннектов? Или на каждый запрос открывается/закрывается физически новое подключение?


Конечно нет.
Открываешь/закрываешь новое подключение к бд вручную, как и везде обычно.

Автор: Soteric 23.7.2017, 1:26

Цитата(Aimed @ 22.7.2017, 22:53) *

Конечно нет.
Открываешь/закрываешь новое подключение к бд вручную, как и везде обычно.

Везде обычно коннект открывается один раз в начале работы с базой и потом переиспользуется.

Автор: Aimed 23.7.2017, 3:32

Цитата(Soteric @ 23.7.2017, 0:26) *

Везде обычно коннект открывается один раз в начале работы с базой и потом переиспользуется.


При синхронной работе почти всегда открывается коннект и в try/catch блоке выполняется то что надо и коннект закрывается.

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

Если у тебя есть просто очередь для асинхронной работы с бд и иногда в цикле в очередь могут попасть запросы, то при разгрузке открывают и закрывают.
Мне ща лень рыться в исходниках сферы, но я более чем уверен что они для своих AQUERY/AEXECUTE тоже открывают и закрывают коннект.

Лучше лишний раз открыть и закрыть, нежели проворонить где-то этот момент и создать потенциальную утечку, которую решить может только перезагрузка БД.

Автор: Reality Audit 23.7.2017, 10:09

Цитата(Aimed @ 22.7.2017, 22:53) *

Гипотетическая задача была дана, - сделать топ500. Дальше можно самому додумать.
Конечно нет.
Открываешь/закрываешь новое подключение к бд вручную, как и везде обычно.


Предположим, делаем топ500 (пробежался по сайтам шардов, чтобы заценить что именно туда выносят)
Почти все нужная инфа есть на чаре в дефолтных полях (киллы/карма) или в тегах (опыт или лвл, например) или по соседству (на аккаунте).
Самый зверский способ - писать в базу каждый раз при изменении атрибута. Если онлайн небольшой, можно не запариваться и так и сделать. Если сервер упал или был откат - при старте можно перекалькулировать

Компромисс - писать в какое-то время всё целиком и привязать это, например, к сейву. Засейвились, открыли коннекцию к базе, пробежались по чарам/аккаунтам, скинули в базу, закрыли коннект.

Автор: Soteric 23.7.2017, 13:54

Цитата(Aimed @ 23.7.2017, 3:32) *

При синхронной работе почти всегда открывается коннект и в try/catch блоке выполняется то что надо и коннект закрывается.

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

Если у тебя есть просто очередь для асинхронной работы с бд и иногда в цикле в очередь могут попасть запросы, то при разгрузке открывают и закрывают.
Мне ща лень рыться в исходниках сферы, но я более чем уверен что они для своих AQUERY/AEXECUTE тоже открывают и закрывают коннект.

Лучше лишний раз открыть и закрыть, нежели проворонить где-то этот момент и создать потенциальную утечку, которую решить может только перезагрузка БД.

blink.gif

Даже https://habrahabr.ru/post/101342/ понимает, что новый коннект это ненужные накладные расходы и старается их избежать.

Автор: Llirik 23.7.2017, 15:15

У меня коннект открывается всего лишь 1 раз при старте сферы и я работаю с базой и нигде её не закрываю. Я думаю 1 коннект это нормально. И закроется он сам.

Да правильнее было бы всё закрывать руками, но, как же сборка мусора и т.д. т.е. программа сама может закрыть.

А не дрочить каждый раз DB.CONNECT DB.CLOSE, как дятел.

Мой ответ: "Без разницы!" с 1 постоянно открытым коннектом я думаю ничего страшного не случиться и к тому же он убьётся при закрытии сферы.

Автор: Juzzver 23.7.2017, 19:32

Цитата
И закроется он сам.

А если он по каким либо причинам закроется еще до того, как ты его начнешь переиспользовать?) Как ты намерен это проверять? smile.gif

Цитата
как же сборка мусора

Сомневаюсь, что она там реализована smile.gif, если и реализована - то на уровне ядра. И закрывать коннекты БД она вряд ли будет, если это изначально не было заложено.

Автор: Reality Audit 23.7.2017, 19:47

Цитата(Soteric @ 23.7.2017, 13:54) *

blink.gif

Даже https://habrahabr.ru/post/101342/ понимает, что новый коннект это ненужные накладные расходы и старается их избежать.


Шикарный пример biggrin.gif

Если ты знаешь, что делаешь и что там под капотом - отлично. В случае топик стартера я бы предложил следовать мануалу, пока не придет понимание и опыт

Автор: Aimed 24.7.2017, 0:02

Цитата(Soteric @ 23.7.2017, 12:54) *

blink.gif

Даже https://habrahabr.ru/post/101342/ понимает, что новый коннект это ненужные накладные расходы и старается их избежать.


Оно и видно что джуниор и статья 2010 года.
Во первых, на сегодняшний день апликации стараются делать мультипоточными и для работы с БД это делается как я описал выше - с очередями по producer/consumer принципу. Либо через всякие async/await/Task.
Потому что работа прозводится в отдельном потоке, те пару мс или даже секунд для создания соединения роли не играют, гораздо важнее что бы не было утечек.

(Внимание, потенциально опасная тема для холивара!)
Во вторых, singleton шаблон, это устаревший шаблон который как можно быстрее желательно забыть и не вспоминать. Для современных, мультипоточных апликаций желательно создавать новые обьекты и клонировать все это дело на крайний случай, что-бы не было веселых ситуаций с race conditions или всяких проблем от того что понавставлено 100500 локов и в коде все это выглядит как настоящий ад, а каждое изменения такого кода приводит к потецинальному дед локу.\

В третьих, обычно если со Сферы что-то загоняют в БД, этой БД желательно находится на той-же самой машине и создание соединения там будет длиться 0 времени. Ежели БД на другом сервере где-то в сети, лучше просто работать через AEXECUTE/AQUERY.

Цитата(Reality Audit @ 23.7.2017, 9:09) *

Предположим, делаем топ500 (пробежался по сайтам шардов, чтобы заценить что именно туда выносят)
Почти все нужная инфа есть на чаре в дефолтных полях (киллы/карма) или в тегах (опыт или лвл, например) или по соседству (на аккаунте).
Самый зверский способ - писать в базу каждый раз при изменении атрибута. Если онлайн небольшой, можно не запариваться и так и сделать. Если сервер упал или был откат - при старте можно перекалькулировать

Компромисс - писать в какое-то время всё целиком и привязать это, например, к сейву. Засейвились, открыли коннекцию к базе, пробежались по чарам/аккаунтам, скинули в базу, закрыли коннект.



Хм, да, забыл что может сервер упасть и случиться откат. Смешно вышло, потмоу что сам не так давно занимался системой сейвов для РанУО в реальном времени с сохранением изменений в базу на каждом тике в главном цикле ))

На самом деле это не зверский способ, примерно так на сегодняшний день сохраняют данные современные ММОРПГ.
Для УО, с её сейвами в файл с остановлением сервера правда лучше после сейва брать все это дело.
А потому что речь идёт о Сфере, в которой нет возможности писать мультипоточный код, лучше все-таки сделать отдельную программу и парсить файл с сейвами, что-бы не мешать Сфере работать и не удлиннять сейвы и не создавать лаги для игроков. Соберая данные для БД из всех плееров по какому-то таймеру раз в х времени может записать неактуальные данные в базу если сервер откатится, а так-же может создать лаги, потому что все это будет происходить в главном треде Сферы.

Автор: Aimed 24.7.2017, 0:45

Цитата(Llirik @ 23.7.2017, 14:15) *

У меня коннект открывается всего лишь 1 раз при старте сферы и я работаю с базой и нигде её не закрываю. Я думаю 1 коннект это нормально. И закроется он сам.

Да правильнее было бы всё закрывать руками, но, как же сборка мусора и т.д. т.е. программа сама может закрыть.

А не дрочить каждый раз DB.CONNECT DB.CLOSE, как дятел.

Мой ответ: "Без разницы!" с 1 постоянно открытым коннектом я думаю ничего страшного не случиться и к тому же он убьётся при закрытии сферы.


Твой ответ ничего не значит потому что ты не смотрел в исходники Сферы. Ты лишь предполагаешь.
Я только что посмотрел на исходники из мастер ветки на гитхабе ( ХЗ что там в старых исходниках 56б ).
Там вызов закрытия соединения только в деструкторе обьекста CDataBase ( который выполняется при закрытии сервера )и различные закрытия при попытках оперировать с БД, но при этом БД не отвечает.
Сферовци сами реализовали обьект соединения с БД как синглтон. Так-же нельзя иметь одновременно соединения с двумя разными БД.

При краше Сферы или переполнении стека ( бесконечный цикл ), у тебя будет утечка одного коннекта в самой БД уже.
(Можно ещё как вариант глянуть в самой MySQL?(если речь о ней), есть ли там какой-то уборщик соединений которые не использовалишь дольше чем х времени и просто удалять их, освобождая тред. Наверняка должно что-то такое быть. На крайняк сделать свой скрипт и поставить на выполнение по расписанию)
"А не дрочить каждый раз DB.CONNECT DB.CLOSE, как дятел"
Зачем, если это можно мопестить в одну функцию и вызывать её постоянно, передавая ей в аргументы то что тебе нужно?

В принципе у Сферы нормальная стабильность, если руки на месте. Держать коннект постоянно открытым можно, но я не могу назвать это нормальной практикой smile.gif

Автор: Aimed 24.7.2017, 0:58

Цитата(Juzzver @ 23.7.2017, 18:32) *

А если он по каким либо причинам закроется еще до того, как ты его начнешь переиспользовать?) Как ты намерен это проверять? smile.gif


Да там у них в ядре везде проверки есть для этого, правда я исходники текущей D версии смотрел, а у местных здесь обычно старая 56б в обороте.

В принципе для самой Сферы это не критично. Там даже дизайн такой, с расчетом на то что коннект к БД будет открыт всю сессию самого сервера.

Во всех остальных случаях, лично я против такой практики.

Автор: Llirik 24.7.2017, 20:46

Каких нах утечек? Вы знаете, что надо создавать так:
DB.EXECUTE "UPDATE register SET activ='1' WHERE login='<DB.ROW.<LOCAL._FOR>.0>' LIMIT 1"

Я создаю так:
DB.EXECUTE UPDATE register SET activ="1" WHERE login="<DB.ROW.<LOCAL._FOR>.0>"

без каких либо кавычек или апострофов!

Автор: Aimed 25.7.2017, 5:01

Цитата(Llirik @ 24.7.2017, 19:46) *

Каких нах утечек? Вы знаете, что надо создавать так:
DB.EXECUTE "UPDATE register SET activ='1' WHERE login='<DB.ROW.<LOCAL._FOR>.0>' LIMIT 1"

Я создаю так:
DB.EXECUTE UPDATE register SET activ="1" WHERE login="<DB.ROW.<LOCAL._FOR>.0>"

без каких либо кавычек или апострофов!


Ты не в теме.

Автор: Reality Audit 25.7.2017, 18:37

Цитата(Llirik @ 24.7.2017, 20:46) *

Каких нах утечек? Вы знаете, что надо создавать так:
DB.EXECUTE "UPDATE register SET activ='1' WHERE login='<DB.ROW.<LOCAL._FOR>.0>' LIMIT 1"

Я создаю так:
DB.EXECUTE UPDATE register SET activ="1" WHERE login="<DB.ROW.<LOCAL._FOR>.0>"

без каких либо кавычек или апострофов!


Индус? О_о

Автор: Llirik 25.7.2017, 20:37

Вы каждый раз файл через [EOF] закрываете?

Автор: Reality Audit 27.7.2017, 17:56

Цитата(Llirik @ 25.7.2017, 20:37) *

Вы каждый раз файл через [EOF] закрываете?

Давай сверим часы чувак, сейчас четверг гребанного июльского лета 2017 года. А затем ты в срочном порядке пройдешь тест на инопланетянина.

Автор: Aimed 27.7.2017, 19:05

Цитата(Reality Audit @ 27.7.2017, 16:56) *

Давай сверим часы чувак, сейчас четверг гребанного июльского лета 2017 года. А затем ты в срочном порядке пройдешь тест на инопланетянина.


Не, это у него такая свойственная манера общения.
Это он пытается аргументировать ненадобность закрывать коннект к бд на примере работы с файлом. Только я не понимаю причем тут eof

Автор: Reality Audit 28.7.2017, 16:09

Цитата(Aimed @ 27.7.2017, 19:05) *

Не, это у него такая свойственная манера общения.
Это он пытается аргументировать ненадобность закрывать коннект к бд на примере работы с файлом. Только я не понимаю причем тут eof


Боюсь, он и сам не понимает biggrin.gif

Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)