L2 Server Database Setup: MySQL and MariaDB Done Right

A clean l2 server database setup is the difference between a world that survives a restart and one that loses accounts, items and clan data. The database holds all persistent player and world state: accounts, characters, inventory, clans, castles and logs. NPCs, spawns and item templates live in the datapack instead. The game server can be rebuilt from source in an afternoon, but a corrupted or half-installed schema can cost you the players. This guide covers the engine choice, a safe install, loading the L2J schema, the settings that actually matter, and the failures you will hit on the way.
MariaDB or MySQL: Pick One and Match the Pack
L2J is compatible with MySQL 8.0 and newer, but the project recommends MariaDB. The L2J schema runs on both, both work with a JDBC driver, and both are fine in production when configured with care. The engines are not identical under the hood, so pick one, match the connector your pack ships with, and do not install a second engine because a tutorial used it.
| Point | MariaDB | MySQL 8.0+ |
|---|---|---|
| L2J recommendation | Preferred | Compatible |
| Default in most packs | Yes | Optional |
| Configuration file | my.cnf / my.ini | my.cnf / my.ini |
| JDBC driver | MariaDB Connector/J | MySQL Connector/J |
Check which driver your pack ships with before you install anything. A pack built for one connector can still connect to the other engine in many cases, but the URL syntax and some defaults differ. Guessing here produces connection errors that look like password problems.

Install and Secure the Engine
On Windows, the MariaDB or MySQL installer creates the service, the data directory and the root account. On Debian or Ubuntu, the package does the same and starts the service. Either way, run the secure installation step immediately after a fresh install.
- Set a root password you do not reuse anywhere else.
- Remove anonymous users and the test database.
- Disallow remote root login.
- Reload the privilege tables so the changes apply at once.
On many Linux packages the root account authenticates through the local socket rather than a password. That is a security feature, not a bug. It means the command line works while a remote root connection does not, and it explains the first confusing "access denied" moment for new owners.
Keep the server bound to localhost. If the game server runs on the same machine, there is no reason for port 3306 to answer the internet, and automated scanners find exposed database ports quickly.
Create the User and the Database
Do not run the game server as root. Create one dedicated account, give it exactly what it needs, and use a password long enough that it cannot be guessed. A minimal setup looks like this:
- Create the database, for example
l2jdb. - Create a user such as
l2j, restricted tolocalhostwhen the server is local. - Grant privileges on that database only, not on everything.
- Flush privileges and test the login from the command line.
Some tutorials grant the account full rights with a wildcard host. That is convenient for a temporary test box and a bad habit for a live server. If your database is on a separate machine, restrict the host to that private address and firewall the port between the two hosts.

Load the L2J Schema
Modern L2J ships a CLI that installs the SQL files for you, including custom and mod tables. Older packs expect you to import the login and game SQL files manually through phpMyAdmin, HeidiSQL or the command line. Both approaches work, but the order matters.
- Install the login schema first, then the game schema.
- Use the full installation mode on a new database, not the update mode.
- Confirm the table count instead of trusting the progress bar.
- Check that the account table and the character tables both exist.
If the game server starts but the login server refuses connections, a half-installed schema is one of the first things to check. The two services use different tables, and a missing set breaks only part of the stack.
Point the Server at the Database
The connection details live in the login server config folder and again in the game server config folder. They are separate files, and both need the same host, port, database name, user and password. Editing one and forgetting the other is the most common setup mistake.
After a change, restart both services in order: database, then login server, then game server. The game server registers with the login server, so starting them backwards can leave the world out of the server list until the game server reconnects, even though both processes are running.
Tuning That Actually Matters
Default settings are built for small test installs. On a live server, a few values do most of the work:
- Buffer pool: give InnoDB a large share of RAM on a database-only host, commonly half to two thirds. It caches data and indexes, and a cold buffer pool is the usual reason the first minutes after a restart feel slow.
- Connections: raise the connection limit above your pack's pool size, with headroom for admin tools and backups.
- Durability versus speed: the log flush setting trades a small risk of losing the last second of commits for faster writes. Keep the safe value on a live economy unless you understand the trade.
- Name resolution: disabling reverse DNS lookups with
skip_name_resolvespeeds up connections, but MySQL then matches grants by IP address instead of hostname. If you enable it, create the user for the client IP, or forlocalhostwhen the connection uses the socket. - Charset: keep the charset the pack ships with. Converting a live database to a different collation is a migration, not a checkbox.
Change one setting at a time and restart cleanly. Two changes at once teach you nothing when performance improves or breaks.
Backups and Restore Drills
A backup you have never restored is a hope, not a backup. Take a logical dump with a consistent snapshot, compress it, and copy it off the machine on a schedule.
- Dump the whole database, not just the character tables.
- Include routines and triggers if your pack uses them.
- Keep several days of dumps and at least one copy on different storage.
- Restore into a scratch database once a month and check a character login.
Before every patch or migration, take a manual dump and label it with the version. The automated schedule protects you from hardware failure, but the manual snapshot is what saves you from your own update.
Common Errors and What They Mean
| Error | Usual cause | Fix |
|---|---|---|
| Access denied for user | Wrong host, password or auth plugin | Check the user host, reset the password, test locally |
| Unknown database | Schema name does not match the config | Create it or correct the JDBC URL |
| Communications link failure | Service stopped, wrong port or firewall | Start the engine, verify the port, keep it private |
| Too many connections | Pool size above the server limit | Raise the limit or lower the pool |
| Incorrect string value | Charset mismatch on imported data | Use the pack's charset for the dump and the database |
A Database You Can Trust
Keep it small and boring: one engine, one dedicated user, a schema installed in full, a local-only port and a tested dump schedule. That setup will not win an architecture argument, but it will keep your world online through patches, crashes and the occasional bad night.
Once the server is stable, the next problem is players. List your world through the free listing form, or use VIP placement to stand out in the server directory.
