Logo

MySQLOO: connect your Garry's Mod server to MySQL

MySQLOO: connect your Garry's Mod server to MySQL

Install mysqloo (MySQL Lua module for GMod), connect your VeryCloud Wisp server to a MySQL/MariaDB DB, and write the first queries for your gamemode (DarkRP, TTT, custom).

Prerequisites

  • A GMod server at VeryCloud
  • An accessible MySQL/MariaDB DB
  • Access to Files in Wisp

Step 1: Choose the mysqloo version

On VeryCloud Wisp (Linux x64), grab gmsv_mysqloo_linux64.dll (the .dll extension stays under Linux — GMod convention).

Step 2: Upload the binary

In Wisp → Files/garrysmod/lua/bin/:

  1. Create the folder if it doesn't exist
  2. Upload gmsv_mysqloo_linux64.dll

Restart.

Step 3: Verify load

At boot, console:

require("mysqloo")

No error = loaded. Otherwise check architecture (32 vs 64 bit) and filename.

Step 4: Prepare the DB

CREATE DATABASE gmod_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'gmod_user'@'IP_OF_GMOD_SERVER' IDENTIFIED BY 'solid_password_16_chars';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, ALTER, DROP
  ON gmod_db.*
  TO 'gmod_user'@'IP_OF_GMOD_SERVER';
FLUSH PRIVILEGES;

⚠️ Never use % for host. Specify the GMod server IP (from Wisp → Network).

Step 5: First Lua script with mysqloo

Create /garrysmod/lua/autorun/server/db_init.lua:

require("mysqloo")

local DB_HOST = "your.mysql.host"
local DB_USER = "gmod_user"
local DB_PASS = "solid_password_16_chars"
local DB_NAME = "gmod_db"
local DB_PORT = 3306

DB = mysqloo.connect(DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT)

function DB:onConnected()
    print("[DB] MySQL connection OK")
end

function DB:onConnectionFailed(err)
    print("[DB] Connection failed: " .. err)
end

DB:connect()

Restart. Should print [DB] MySQL connection OK.

Step 6: First query

local q = DB:query("CREATE TABLE IF NOT EXISTS players (\
    steamid VARCHAR(20) PRIMARY KEY,\
    name VARCHAR(64),\
    money INT DEFAULT 500,\
    last_login DATETIME\
)")

function q:onSuccess()
    print("[DB] players table created")
end

function q:onError(err)
    print("[DB] Table creation error: " .. err)
end

q:start()

All mysqloo queries are async: declare onSuccess and onError callbacks, then :start().

Step 7: Common patterns

SELECT:

local function GetPlayerMoney(ply, cb)
    local q = DB:query(string.format(
        "SELECT money FROM players WHERE steamid = %s",
        DB:escape(ply:SteamID())
    ))
    function q:onSuccess(data)
        cb(tonumber(data[1] and data[1].money) or 0)
    end
    function q:onError(err)
        print("[DB] error: " .. err)
        cb(0)
    end
    q:start()
end

Prepared statement:

local stmt = DB:prepare("UPDATE players SET money = ? WHERE steamid = ?")
stmt:setNumber(1, 1000)
stmt:setString(2, ply:SteamID())
function stmt:onSuccess() print("[DB] Update OK") end
function stmt:onError(err) print("[DB] Error: " .. err) end
stmt:start()

Always prefer prepared statements — performance + SQL injection protection.

Step 8: Auto-reconnection

mysqloo handles silent disconnects poorly (MySQL idle timeout). Reconnection pattern:

function DB:onConnectionFailed(err)
    print("[DB] Connection lost, retry in 5s...")
    timer.Simple(5, function() DB:connect() end)
end

Or periodic ping to keep alive:

timer.Create("DB_Ping", 60, 0, function()
    local q = DB:query("SELECT 1")
    function q:onError(err)
        print("[DB] Ping failed, reconnecting...")
        DB:connect()
    end
    q:start()
end)

Step 9: DarkRP integration

DarkRP uses MySQLite on top of mysqloo (or SQLite). Configure in /garrysmod/addons/darkrpmodification/lua/darkrp_config/mysql.lua. Other DarkRP-compatible addons automatically use your connection.

Step 10: Security

  • Dedicated MySQL account per app/server
  • Source IP restricted (never %)
  • Long password, never committed to Git
  • TLS for MySQL if the connection leaves the datacenter
  • Regular DB backups (mysqldump cron + offsite)

Troubleshooting

Module not found: mysqloo — wrong location (must be /garrysmod/lua/bin/), wrong arch. Access denied for user — wrong password, source IP not in GRANTs. Can't connect to MySQL server — port 3306 firewall, GMod server IP changed. Slow queries / freezes — not using async (verify :start() and callbacks).

Useful commands

lua_run print(DB:status() == mysqloo.DATABASE_CONNECTED)
lua_run local q = DB:query("SHOW TABLES") q.onSuccess = function(self, data) PrintTable(data) end q:start()
DB:escape(text)

Conclusion

mysqloo = cornerstone of any serious GMod server: persistent economy, player stats, bans, logs. 30 min setup with a prepared DB. Always async, always prepared statements for user inputs. Once in place, all your addons (DarkRP, ULib MySQL, custom) benefit.

Going further: multi-connection pools for performance, MySQLite (SQLite/MySQL abstraction), monitor DB latency gamemode-side.

Resources

Join our Discord community server

For any questions, suggestions, or just to chat with the community, join us on Discord!

900+Members