Como Otimizar o SQL Server para Melhor Performance no Servidor MU
Aprenda a configurar e otimizar o SQL Server para servidores MU Online privados, com queries, índices e ajustes de memória específicos.
Por que a Performance do SQL Server é Crítica para Servidores MU
O GameServer do MU Online realiza centenas de operações de leitura e escrita no banco de dados por segundo — cada movimento de personagem, item droppado, XP ganho e conexão de conta passa pelo SQL Server. Um banco mal configurado resulta em lag, desconexões e corrupção de dados de personagens.
Este guia cobre ajustes específicos para instalações típicas com o banco MuOnline rodando em Windows Server 2008/2012/2016, SQL Server 2008 a 2019, com Season 4 a 13.
BACKUP DATABASE MuOnline TO DISK = 'C:\Backup\MuOnline_pre_otimizacao.bak';Passo 1 — Configurar Memória Máxima do SQL Server
Por padrão, o SQL Server consome toda a RAM disponível, deixando o GameServer e o Windows sem recursos.
1.1 Abra o SSMS e execute:
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
-- Defina o teto de RAM (ajuste conforme seu servidor)
-- Servidor com 8 GB RAM: reserve 2 GB para SO e GameServer
EXEC sp_configure 'max server memory (MB)', 6144;
RECONFIGURE WITH OVERRIDE;
1.2 Verifique o consumo atual antes e depois:
SELECT
physical_memory_in_use_kb / 1024 AS MB_em_uso,
page_fault_count
FROM sys.dm_os_process_memory;
Passo 2 — Configurar o Modo de Recuperação do Banco
O banco MuOnline raramente precisa de recuperação point-in-time. Manter o modo FULL gera logs enormes sem benefício prático.
2.1 Altere para modo SIMPLE:
ALTER DATABASE MuOnline SET RECOVERY SIMPLE;
ALTER DATABASE MuOnline_Log SET RECOVERY SIMPLE; -- se existir banco separado de logs
2.2 Reduza o arquivo de log imediatamente:
USE MuOnline;
DBCC SHRINKFILE (MuOnline_log, 50); -- reduz para 50 MB
DBCC SHRINKFILE (MuOnline_data, 0); -- libera páginas não utilizadas
Passo 3 — Criar Índices nas Tabelas Críticas
As tabelas Character, AccountCharacter e AccountMDItem são as mais acessadas durante o jogo. Sem índices adequados, cada busca faz um full table scan.
3.1 Índices essenciais para a tabela Character:
USE MuOnline;
-- Índice por conta (necessário para login e listagem de personagens)
CREATE INDEX IX_Character_AccountID
ON dbo.Character (AccountID)
INCLUDE (Name, cLevel, MapNumber);
-- Índice por nome (usado em buscas do GameServer e sistemas de trade)
CREATE INDEX IX_Character_Name
ON dbo.Character (Name);
-- Índice composto para o sistema de ranking
CREATE INDEX IX_Character_Ranking
ON dbo.Character (cLevel DESC, Resets DESC, MasterLevel DESC);
3.2 Índices para AccountCharacter (controle de sessão):
CREATE INDEX IX_AccChar_Account
ON dbo.AccountCharacter (AccountID)
INCLUDE (GameIDC);
CREATE INDEX IX_AccChar_ConnectStat
ON dbo.AccountCharacter (ConnectStat, ServerCode);
3.3 Índices para itens armazenados:
-- Tabela de armazém de conta
CREATE INDEX IX_AccountMDItem_AccountID
ON dbo.AccountMDItem (AccountID);
-- Tabela de itens de personagem (Season 6+)
CREATE INDEX IX_Items_CharName
ON dbo.Items (AccountID, CharName);
SELECT name, type_desc FROM sys.indexes WHERE object_id = OBJECT_ID('dbo.Character');Passo 4 — Atualizar Estatísticas e Reconstruir Índices
Índices fragmentados e estatísticas desatualizadas degradam a performance ao longo do tempo, especialmente após wipes ou grandes eventos.
4.1 Script de manutenção semanal — crie como SQL Agent Job:
USE MuOnline;
-- Atualiza estatísticas de todas as tabelas
EXEC sp_updatestats;
-- Reconstrói índices fragmentados acima de 30%
DECLARE @TableName NVARCHAR(256);
DECLARE @IndexName NVARCHAR(256);
DECLARE @SQL NVARCHAR(MAX);
DECLARE idx_cursor CURSOR FOR
SELECT
OBJECT_NAME(i.object_id),
i.name
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ps
JOIN sys.indexes i ON ps.object_id = i.object_id AND ps.index_id = i.index_id
WHERE ps.avg_fragmentation_in_percent > 30
AND i.name IS NOT NULL;
OPEN idx_cursor;
FETCH NEXT FROM idx_cursor INTO @TableName, @IndexName;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SQL = 'ALTER INDEX [' + @IndexName + '] ON dbo.[' + @TableName + '] REBUILD;';
EXEC sp_executesql @SQL;
FETCH NEXT FROM idx_cursor INTO @TableName, @IndexName;
END;
CLOSE idx_cursor;
DEALLOCATE idx_cursor;
Passo 5 — Otimizar as Configurações de Conexão do GameServer
O arquivo de configuração do GameServer define como ele se conecta ao SQL. Localize o arquivo em GameServer/Data/ — pode ser DBServer.ini, GameServerInfo.cfg ou similar dependendo da sua versão.
5.1 Configurações recomendadas para DBServer.ini (Season 6):
[DBServer]
ConnectServer = 127.0.0.1 ; use IP local sempre que possível
Port = 1433
DatabaseName = MuOnline
UserID = muonline_user ; NUNCA use sa em produção
Password = SenhaNaoUseAdmin123!
ConnectionTimeout = 30
QueryTimeout = 60
MaxConnections = 50
5.2 Crie um usuário SQL dedicado com permissões mínimas:
-- Cria login
CREATE LOGIN muonline_user WITH PASSWORD = 'SenhaNaoUseAdmin123!';
-- Cria usuário no banco
USE MuOnline;
CREATE USER muonline_user FOR LOGIN muonline_user;
-- Concede apenas o necessário
ALTER ROLE db_datareader ADD MEMBER muonline_user;
ALTER ROLE db_datawriter ADD MEMBER muonline_user;
GRANT EXECUTE TO muonline_user;
sa para conectar o GameServer. Se o GameServer for comprometido, o atacante terá controle total do SQL Server.Passo 6 — Monitorar Queries Lentas em Tempo Real
6.1 Identifique as queries que mais consomem CPU:
SELECT TOP 20
qs.total_elapsed_time / qs.execution_count / 1000 AS avg_ms,
qs.execution_count,
qs.total_logical_reads / qs.execution_count AS avg_reads,
SUBSTRING(qt.text, (qs.statement_start_offset/2)+1,
((CASE qs.statement_end_offset WHEN -1 THEN DATALENGTH(qt.text)
ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)+1) AS query_text
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
ORDER BY avg_ms DESC;
6.2 Identifique bloqueios entre conexões (útil durante eventos):
SELECT
blocking_session_id AS bloqueador,
session_id AS bloqueado,
wait_type,
wait_time / 1000 AS espera_seg,
SUBSTRING(st.text, (r.statement_start_offset/2)+1, 200) AS query
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) st
WHERE blocking_session_id > 0;
Passo 7 — Agendar Manutenção Automática via SQL Agent
7.1 Crie um Job no SQL Agent (SSMS → SQL Server Agent → Jobs → New Job):
- Nome:
MuOnline - Manutencao Semanal - Schedule: Toda segunda-feira às 04:00
- Step 1: Execute o script de reconstrução de índices do Passo 4
- Step 2:
USE MuOnline;
DBCC SHRINKFILE (MuOnline_log, 100);
EXEC sp_updatestats;
PRINT 'Manutencao concluida em: ' + CONVERT(VARCHAR, GETDATE(), 120);
Troubleshooting Rápido
| Sintoma | Causa Provável | Solução |
|---|---|---|
| Login demora mais de 5 segundos | Full scan em AccountCharacter | Criar índice em AccountID + ConnectStat |
| Servidor trava ao entrar em Blood Castle | Lock em tabela de eventos | Verificar bloqueios com query do Passo 6.2 |
| CPU do SQL a 100% em horário de pico | Estatísticas desatualizadas | Executar sp_updatestats manualmente |
| Arquivo .mdf cresce sem parar | Auto-growth mal configurado | Definir crescimento fixo: ALTER DATABASE MuOnline MODIFY FILE (NAME = MuOnline, FILEGROWTH = 256MB); |
Com essas otimizações aplicadas, servidores Season 6 com 200-500 jogadores simultâneos tipicamente reduzem o lag de database em 60-80%. Monitore os contadores com as queries de diagnóstico semanalmente e reajuste os limites de memória conforme a carga do servidor evoluir.
Perguntas frequentes
Qual versão do SQL Server é mais recomendada para Season 6?
O SQL Server 2008 R2 ou 2012 são os mais testados e estáveis para Season 6. O 2019 também funciona, mas exige ajustes no nível de compatibilidade do banco: execute ALTER DATABASE MuOnline SET COMPATIBILITY_LEVEL = 100; para emular comportamento do 2008.
O servidor MU trava durante eventos como Blood Castle ou Devil Square. O que fazer?
Esses eventos geram picos de escrita na tabela Character e AccountCharacter. Crie índices nas colunas AccountID e Name com CREATE INDEX IX_Char_Account ON MuOnline.dbo.Character (AccountID); e agende reconstrução de índices semanalmente com ALTER INDEX ALL ON MuOnline.dbo.Character REBUILD;
Como saber se o SQL Server está consumindo memória demais?
Execute SELECT physical_memory_in_use_kb/1024 AS MB_usado FROM sys.dm_os_process_memory; Se ultrapassar 80% da RAM do servidor, reduza o teto com sp_configure 'max server memory (MB)', 2048; RECONFIGURE; ajustando o valor conforme sua RAM disponível.
Os logs do SQL Server estão crescendo demais e enchendo o disco. Como controlar?
Coloque o banco em modo SIMPLE com ALTER DATABASE MuOnline SET RECOVERY SIMPLE; depois execute DBCC SHRINKFILE (MuOnline_log, 50); para reduzir o arquivo de log para 50 MB. Em produção, agende esse processo semanalmente via SQL Agent Job.