Servidores de Jogos

Otimizando consultas com dbQuery assíncrono

Otimizando consultas com dbQuery assíncrono

Um dos motivos mais comuns de "congelamentos" em servidores de MTA é o banco de dados sendo consultado de forma síncrona. Enquanto o servidor espera a resposta, o jogo inteiro para.

O problema: dbPoll com -1

-- trava o servidor até a consulta terminar
local qh = dbQuery(db, "SELECT * FROM contas WHERE usuario = ?", usuario)
local resultado = dbPoll(qh, -1)

O -1 faz o servidor esperar pelo resultado. Com o banco rápido e pouca gente, passa despercebido. Com muitos jogadores ou uma consulta lenta, gera picos de lag para todos.

A solução: callback

dbQuery(function(qh, jogador)
    local resultado = dbPoll(qh, 0)
    if not isElement(jogador) then return end -- jogador saiu enquanto esperava
    if not resultado then
        return outputDebugString("Erro na consulta de login", 1)
    end
    processarLogin(jogador, resultado[1])
end, {jogador}, db, "SELECT * FROM contas WHERE usuario = ?", usuario)
  • O servidor continua rodando enquanto a consulta acontece;
  • Quando termina, a função é chamada com o resultado;
  • Argumentos extras (como o jogador) são passados em uma tabela;
  • Sempre verifique se o jogador ainda existe no callback.

Escritas sem resposta: dbExec

Para INSERT, UPDATE e DELETE em que você não precisa do retorno:

dbExec(db, "UPDATE personagens SET dinheiro = ? WHERE id = ?", dinheiro, id)

Índices

Consultas lentas geralmente são falta de índice. Se você busca por usuario, conta_id ou dono, essas colunas precisam de índice:

CREATE INDEX idx_veiculos_dono ON veiculos (dono);

Busque só o necessário

-- ruim
SELECT * FROM personagens;

-- bom
SELECT id, nome, dinheiro FROM personagens WHERE conta_id = ?;

Use LIMIT em listagens e rankings.

Evite consultas em loop

-- ruim: uma consulta por jogador
for _, jogador in ipairs(getElementsByType("player")) do
    dbExec(db, "UPDATE ... WHERE id = ?", ...)
end

Prefira:

  • Dados em memória, salvos periodicamente;
  • Consultas agrupadas quando possível;
  • Espalhar salvamentos ao longo do tempo (não todos no mesmo segundo).

Cache

Dados que mudam pouco (preços de lojas, configurações, lista de casas) podem ser carregados uma vez no início do resource e mantidos em memória.

Hospede seu servidor com a VittHost

Todos os planos MTASA-BR da VittHost incluem 1 banco MySQL. Servidores no Brasil, painel Pterodactyl, proteção DDoS, downloads acelerados por nginx dedicado e teste grátis de 3 dias.

Compartilhar:

Pronto para hospedar seu próximo projeto?

VPS com painel pré-instalado em 1 clique. Ativação imediata.

Ver planos VPS