How to migrate MU Online emulators without losing the database
Switch MU Online emulators (IGCN, MuEMU, X-Team, Season 6 → a new season) while preserving accounts, characters, inventory, and Warehouse: SQL Server backup, table mapping, schema adjustment, and testing before opening to players.
Switching emulators is one of the most delicate steps in the life of a MU Online server: you want the new emulator's features (better anti-cheat, new systems, more stability), but you can't lose the accounts, characters, inventories, and Warehouses that players have built. A botched migration wipes
Switching emulators is one of the most delicate steps in the life of a MU Online server: you want the new emulator's features (better anti-cheat, new systems, more stability), but you can't lose the accounts, characters, inventories, and Warehouses that players have built. A botched migration wipes out months of progress and kills the server in a day. A well-executed migration is invisible to the player: they log in and everything is there. This tutorial walks through the complete process — backup, table mapping, schema conversion, and testing — always working on copies and never on the production database.
Why migrations go wrong (and how to avoid it)
Most migration disasters come from three mistakes: touching the production database directly, assuming the schemas are identical between emulators, and opening the server without testing. MU Online, in the vast majority of emulators (IGCN, MuEMU, X-Team, among others), uses Microsoft SQL Server as its database. That's good news: the core tables have similar names and structures across emulators, because they all descend from the same original files. The bad news is that "similar" is not "identical" — column names, field sizes, and the binary inventory format vary. A safe migration always treats the old database as a read source and builds the new one in parallel.
Prerequisites
- The old server still functional, with access to SQL Server (the
sauser or equivalent). - The new emulator already installed and tested with a clean database (see the server creation tutorial).
- SQL Server Management Studio (SSMS) for backup, restore, and queries.
- Disk space for at least two complete copies of the database.
- A maintenance window with the server offline (no migrating live).
- A validated backup before any change — this one is non-negotiable.
Understand MU's core tables
Before moving any data, know what needs to survive. The names vary by emulator, but the core is always this:
| Table | What it holds | Criticality |
|---|---|---|
MEMB_INFO | Accounts (login, password, email) | Maximum |
AccountCharacter | Which characters belong to each account | Maximum |
Character | Characters: level, stats, class, position | Maximum |
warehouse | Warehouse/Vault and stored Zen | Maximum |
Guild / GuildMember | Guilds and members | High |
MEMB_STAT | Account online/offline status | Low (regenerable) |
The character's inventory usually is not a separate table: it lives inside a binary field (Inventory) in the Character table. That detail is the heart of the migration — we'll come back to it in Step 4.
Step 1 — Full backup of the old database
With the GameServer and ConnectServer stopped, take a full backup via SSMS or T-SQL. Never start anything without this step completed and verified:
-- Full backup of the old production database
BACKUP DATABASE [MuOnline]
TO DISK = N'D:\Backups\MuOnline_pre_migracao.bak'
WITH FORMAT, INIT,
NAME = N'MuOnline - pre-migration backup',
STATS = 10;
GO
-- Verify the integrity of the backup file
RESTORE VERIFYONLY
FROM DISK = N'D:\Backups\MuOnline_pre_migracao.bak';
GO
The RESTORE VERIFYONLY confirms that the .bak file is intact and restorable. If it fails, stop everything — your backup is no good and you can't risk the migration.
Step 2 — Restore a working copy
Never migrate on the original database. Restore the backup with a new name, which will be your conversion environment. That way, the production database stays untouched if something goes wrong:
-- Restore as a separate working database (MuOnline_MIGRACAO)
RESTORE DATABASE [MuOnline_MIGRACAO]
FROM DISK = N'D:\Backups\MuOnline_pre_migracao.bak'
WITH MOVE 'MuOnline' TO N'D:\SQLData\MuOnline_MIGRACAO.mdf',
MOVE 'MuOnline_log' TO N'D:\SQLData\MuOnline_MIGRACAO_log.ldf',
RECOVERY, STATS = 10;
GO
You get the logical names (MuOnline, MuOnline_log) with RESTORE FILELISTONLY FROM DISK = '...'. From here on, all work happens in MuOnline_MIGRACAO.
Step 3 — Map the schema: old vs. new
Here's the intellectual work of the migration. Install the new emulator with its clean database and compare the structure of each core table between the two. To list a table's columns:
-- Run on both databases and compare column by column
SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, IS_NULLABLE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Character'
ORDER BY ORDINAL_POSITION;
Build a map of differences. The three categories of divergence you'll run into:
| Type of difference | Example (varies by emulator) | Action |
|---|---|---|
| Renamed column | cLevel vs Level | Map it in the copy (INSERT/UPDATE) |
| New column in the new emulator | MasterLevel, PkCount | Fill with a default value |
| Different binary format | Inventory with a distinct layout | Convert byte by byte (Step 4) |
New columns in the destination emulator that didn't exist in the old one should receive a coherent default value (0 for master level, NULL where allowed). Columns that existed in the old one and disappeared in the new one are simply discarded.
Step 4 — The inventory and the Warehouse (the binary field)
This is the point where most migrations fail silently. The inventory and the Warehouse are stored as a hexadecimal blob, where each item occupies a fixed block of bytes (typically 16 bytes per slot in many seasons: item code, level, options, serial, socket, etc.). If the two emulators use the same byte layout, the field is copied as-is and everything is preserved. If the new emulator changed the layout (for example, expanding the block to support new sockets or harmony), you need to convert each block.
A practical rule: before trusting it, take a test character with known items, look at the inventory hex in both formats, and confirm the fields match. Never assume binary blob compatibility — validate with a real case. If the layout diverges, write a conversion script that reads the old blob, reorganizes each item block to the new size, and writes it back.
Step 5 — Migrate the accounts and characters
With the schema mapped, move the data in dependency order: accounts first, then characters, then links and the Warehouse. If the schema is compatible, a direct INSERT between databases does the job; if there are renamed columns, you list the columns explicitly:
-- Example: copy accounts to the new emulator's database
-- (column names vary by emulator — adjust to your schema)
INSERT INTO [MuOnline_NOVO].dbo.MEMB_INFO
(memb___id, memb__pwd, mail_addr, appl_days, bloc_code, ctl1_code)
SELECT
memb___id, memb__pwd, mail_addr, appl_days, bloc_code, ctl1_code
FROM [MuOnline_MIGRACAO].dbo.MEMB_INFO;
GO
Repeat the pattern for Character, AccountCharacter, warehouse, Guild, and GuildMember, always respecting the order so you don't violate foreign keys. Migrate a small batch first (10–20 test accounts) before running the entire base.
Step 6 — Adjust identities, seeds, and constraints
After inserting the data, fix what the INSERT doesn't handle: IDENTITY columns need their seed readjusted, otherwise the next character created collides with an existing ID. Also check that there are no orphaned characters (in Character without an entry in AccountCharacter) or duplicate names:
-- Readjust the identity counter after the bulk load
DBCC CHECKIDENT ('Character', RESEED);
GO
-- Orphaned characters (they exist but belong to no account)
SELECT c.Name
FROM Character c
LEFT JOIN AccountCharacter ac ON c.Name = ac.GameID1 OR c.Name = ac.GameID2
WHERE ac.Id IS NULL;
GO
The orphan query varies depending on whether the emulator stores characters in columns (GameID1..5) or in rows — adapt it to your structure. Any orphan found is a character the player won't see at login.
Step 7 — Point the new emulator and bring it up
Configure the new GameServer/ConnectServer's connection string to the migrated database (the emulator's config file — .ini, .xml, or .dat, varies by emulator). Bring the services up one at a time and watch the logs. A common error here is the emulator failing to start because an auxiliary table it expects (event config, ranking, cash shop) doesn't exist in the migrated database — in that case, create the empty table from the new emulator's clean-database script.
Step 8 — Test in-game before opening
Never open to players without this test battery using real migrated accounts:
- Login: log in with a migrated old account and confirm it authenticates.
- Character selection: all characters appear, with the correct level, class, and resets.
- Stats: strength, agility, life, and mana match the old values.
- Inventory and Warehouse: items present, with options and sockets intact.
- Zen: the character's and the Warehouse's Zen is correct.
- Guild: guilds, marks, and members preserved; ranking coherent.
- Create a new character: confirm it doesn't collide with migrated IDs (validates Step 6).
Only after all items pass do you point the production server at the new database and notify the players.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| GameServer won't connect to the database | Connection string or missing table | Check the config and create the missing auxiliary tables |
| Login OK but no characters appear | AccountCharacter not migrated or orphaned | Verify the account↔character link |
| Items missing or swapped | Divergent inventory blob layout | Convert the binary field (Step 4) |
| Duplicate key error when creating a char | IDENTITY not readjusted | Run DBCC CHECKIDENT ... RESEED |
| Stats or level zeroed out | Renamed column not mapped | Fix the mapping in the INSERT |
| Backup won't restore | Corrupted .bak file | Redo the backup and validate with VERIFYONLY |
Migration checklist
- Old server offline (GameServer and ConnectServer stopped).
- Full backup taken and validated with
RESTORE VERIFYONLY. - Working copy restored under a separate name.
- Core tables' schema compared (old vs. new).
- Inventory/Warehouse format verified with a real case.
- Small batch of accounts migrated and tested before the whole base.
- IDENTITY readjusted and orphans checked.
- New emulator pointed at the migrated database and coming up clean.
- Full in-game test battery passed.
- Original production database preserved until the final cutover.
Once the migration is validated, keep the pre-migration .bak for weeks: if any player reports an item loss that slipped past the tests, you have the original source to check against and fix. A well-documented emulator migration becomes a reusable playbook — on the next version change, you repeat the same steps with far less risk.
Frequently asked questions
Do I need to delete the old database to migrate emulators?
No, and you should never do that. A correct migration starts from a copy (restore) of the old database under another instance/name, and only then adapts the schema for the new emulator. The original production database stays untouched until you validate everything in a test environment.
Does migrating emulators change the table structure?
It depends on how much the two emulators diverge. Core tables like Character, AccountCharacter, and Warehouse usually have similar columns, but names, field sizes, and the inventory encoding vary by emulator. Always compare the schema of both versions before moving data.
Will the character's inventory survive the migration?
Yes, if the inventory field format is compatible. The inventory is a blob/hex with the list of items; if the new emulator uses the same 16-byte-per-item layout (standard in many seasons), it is preserved. If the layout changed (e.g., new socket/harmony support), it needs to be converted.
Can I migrate between different Season versions?
You can, but the bigger the season jump, the greater the chance the schema diverges. Migrating within the same season (just changing emulators) is the safest scenario. Jumping several seasons requires conversion scripts and extra-careful testing, especially for items, sockets, and master level.
How do I know the migration worked before opening the server?
You validate it in a test environment: login works, characters appear with the correct level/stats, inventory and Warehouse intact, Guild and ranking preserved. Only after all these tests pass do you point the production server at the new database.
Should I touch the database with the GameServer running?
Never. Any backup or schema change must be done with the server offline (GameServer and ConnectServer stopped). Altering tables while the game is running corrupts in-transit data and can lock up logged-in players' accounts.