NUOVO 📢 Offerta di lancio limitata: fino al 70% di sconto sul tuo primo mese, per tutti i giochi!Vedi i piani

Come usare un database MySQL con un bot discord.py (aiomysql)

Hosting di bot DiscordUpdated Nov 6, 20268 min read

Risposta breve. Aggiungi aiomysql al tuo bot discord.py, crea un solo pool in setup_hook con autocommit=True ed esegui ogni query attraverso di esso con segnaposto %s. Senza autocommit=True (o un commit() dopo ogni scrittura), aiomysql non salva i tuoi INSERT. Su PlayNHost ogni piano per bot include un database MySQL: crealo nella pagina Database, incolla i suoi dati nel riquadro Ambiente e il codice qui sotto funziona così com'è. Il database accetta connessioni dai tuoi server PlayNHost e da phpMyAdmin, non dal tuo computer. Abbiamo testato questo codice il 6 novembre 2026 con discord.py 2.7.1, aiomysql 0.3.2 e Python 3.12, su MariaDB 10.11 con un account database configurato come il nostro (20 connessioni, limite di 120 secondi per query): l'avvio, la tabella e il comando /warn, ma non un vero login su Discord.

Cosa ti serve

1. Crea il database

  1. Apri il tuo server bot nel pannello e clicca su Database.
  2. Clicca su Nuovo database. Un'Etichetta è facoltativa; Verrà creato come mostra il nome completo. Clicca su Crea database.
  3. Si apre la pagina del nuovo database (più avanti, cliccalo in I tuoi database). La sua scheda Connessione mostra Host, Porta, Database, Nome utente e Password. Sotto Config pronta all’uso, Config per contiene uno snippet Python (aiomysql) con gli stessi valori già compilati.

2. Metti i dati in Ambiente

  1. Apri la pagina Bot, il riquadro Ambiente, e clicca su Incolla un file .env.
  2. Incolla queste cinque righe con i valori della scheda Connessione:
    DB_HOST=your-host
    DB_PORT=3306
    DB_NAME=your-database
    DB_USER=your-username
    DB_PASSWORD=your-password
  3. DB_PASSWORD riceve un badge Segreto: viene salvata in sola scrittura e non viene mai più mostrata. Clicca su Importa 5 variabili.

Usa la porta reale della scheda Connessione. Il tuo codice legge i valori con os.environ, quindi la password non sta mai nei file del tuo bot. Altro su questo riquadro: Come impostare variabili d'ambiente e segreti per il tuo bot Discord.

3. Il codice

requirements.txt

discord.py
aiomysql

bot.py

import os

import aiomysql
import discord
from discord import app_commands


class Bot(discord.Client):
    def __init__(self):
        super().__init__(intents=discord.Intents.default())
        self.tree = app_commands.CommandTree(self)
        self.pool = None

    async def setup_hook(self):
        # One pool for the whole bot. The values come from the Environment pane.
        self.pool = await aiomysql.create_pool(
            host=os.environ["DB_HOST"],
            port=int(os.environ["DB_PORT"]),
            user=os.environ["DB_USER"],
            password=os.environ["DB_PASSWORD"],
            db=os.environ["DB_NAME"],
            autocommit=True,
            maxsize=5,
        )
        async with self.pool.acquire() as conn:
            async with conn.cursor() as cur:
                await cur.execute(
                    "CREATE TABLE IF NOT EXISTS warnings ("
                    "id INT AUTO_INCREMENT PRIMARY KEY, "
                    "guild_id BIGINT UNSIGNED NOT NULL, "
                    "user_id BIGINT UNSIGNED NOT NULL, "
                    "reason VARCHAR(200) NOT NULL, "
                    "created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "
                    "KEY guild_user (guild_id, user_id))"
                )
        print("Database ready")
        await self.tree.sync()

    async def close(self):
        if self.pool is not None:
            self.pool.close()
            await self.pool.wait_closed()
        await super().close()


bot = Bot()


@bot.tree.command(description="Warn a member and count their warnings")
@app_commands.guild_only()
@app_commands.describe(user="Who to warn", reason="Why")
async def warn(interaction: discord.Interaction, user: discord.Member, reason: app_commands.Range[str, 1, 200]):
    async with bot.pool.acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute(
                "INSERT INTO warnings (guild_id, user_id, reason) VALUES (%s, %s, %s)",
                (interaction.guild_id, user.id, reason),
            )
            await cur.execute(
                "SELECT COUNT(*) FROM warnings WHERE guild_id = %s AND user_id = %s",
                (interaction.guild_id, user.id),
            )
            (total,) = await cur.fetchone()
    await interaction.response.send_message(f"{user.mention} has {total} warning(s).")


@bot.event
async def on_ready():
    print(f"Logged in as {bot.user}")


bot.run(os.environ["DISCORD_TOKEN"])

Cosa fa: discord.py esegue setup_hook una sola volta, durante il login e prima che arrivi qualsiasi evento, quindi il pool e la tabella warnings esistono prima che arrivi il primo comando. Poi registra /warn su Discord. @app_commands.guild_only() tiene il comando fuori dai messaggi privati, dove non c'è nessun server a cui associare l'avvertimento. Gli ID Discord stanno in BIGINT UNSIGNED. I segnaposto %s vengono riempiti dal driver, quindi un motivo come '); DROP TABLE warnings; -- viene salvato come semplice testo. Non costruire mai l'SQL con una f-string.

4. Avvialo

  1. Carica bot.py e requirements.txt in Files.
  2. Premi Avvia e apri Console. All'avvio vengono installati i pacchetti da requirements.txt, poi compaiono [PlayNHost] Starting your bot e Database ready.
  3. Su Discord, scrivi /warn. Per vedere le righe, apri la pagina del database e clicca su Apri in phpMyAdmin.

La trappola dell'autocommit

aiomysql apre le connessioni con l'autocommit disattivato. Un INSERT resta allora dentro una transazione aperta. Quando la connessione torna nel pool con quella transazione ancora aperta, aiomysql la chiude e MariaDB scarta la riga non confermata. Nel nostro test, una riga inserita su un pool senza autocommit=True è stata vista da 0 altre connessioni. Passa autocommit=True a create_pool, come sopra, oppure chiama await conn.commit() dopo le tue scritture.

I limiti che contano per il tuo pool

  • 20 connessioni contemporanee per utente del database. Conta ogni processo che usa lo stesso accesso. La connessione 21 viene rifiutata con (1226, "User '...' has exceeded the 'max_user_connections' resource (current value: 20)"). maxsize=5 tiene il bot ben al di sotto.
  • Una query che dura più di 120 secondi viene interrotta. MariaDB la termina con l'errore 1969, Query execution was interrupted (max_statement_time exceeded). Nel nostro test è successo dopo 120.03 secondi. Le query di un bot di solito durano millisecondi, quindi questo riguarda solo una query fuori controllo.
  • 500 MB per database. La pagina Database mostra quanto spazio è usato. A 500 MB le scritture vengono bloccate finché non elimini delle righe.
  • I backup del server non includono il database. Esportalo da phpMyAdmin ogni tanto.

Errori e cosa significano

Questi sono gli errori esatti che aiomysql ha dato nel nostro test (arrivano da PyMySQL, che aiomysql usa sotto il cofano):

  • pymysql.err.OperationalError (1045, "Access denied for user ..."): DB_USER o DB_PASSWORD errati. Dopo Reimposta password nella scheda Connessione, la vecchia password smette di funzionare subito: sostituisci DB_PASSWORD e riavvia il bot.
  • pymysql.err.OperationalError (2003, "Can't connect to MySQL server on ..."): host o porta errati, oppure una connessione dall'esterno di PlayNHost. Il database accetta solo connessioni dai server PlayNHost e da phpMyAdmin, quindi è anche ciò che ottieni dal tuo computer.
  • (1226, ... 'max_user_connections' ...): troppe connessioni aperte, vedi i limiti qui sopra.

Una variabile mancante in Ambiente ferma il bot prima che si connetta, con KeyError: 'DB_HOST' o il nome di quella mancante, perché il codice legge ogni valore con os.environ[...]. Aggiungila e riavvia il bot: le variabili si applicano al successivo avvio.

Altri errori dei bot: Errori comuni dei bot Discord e cosa significano.

Quanta memoria aggiunge

Installare discord.py e aiomysql con pip da zero ha toccato un picco di 78 MB di memoria nel nostro test, in un container limitato a 512 MB come il nostro piano bot più piccolo. Quanta ne serve al bot in esecuzione dipende soprattutto da in quanti server si trova: Di quanta RAM ha bisogno un bot Discord?

Lo stesso in JavaScript, o con Prisma

Ti serve un server bot con database incluso? Guarda i piani per bot.

Il tuo bot è già ospitato altrove? Spostalo da noi

ULTIMI ARTICOLI