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

Come usare Prisma con MySQL in un bot Discord

Hosting di bot DiscordUpdated Nov 6, 20269 min read

Risposta breve. Usa Prisma 7 con l'adapter di driver @prisma/adapter-mariadb, che Prisma documenta per MySQL e MariaDB. Su PlayNHost, prisma migrate dev non può girare sul database del tuo bot, perché deve creare un database "shadow" temporaneo e qui gli utenti dei database non possono creare database. Scrivi invece la prima migrazione con prisma migrate diff, che non richiede alcun database, e lascia che uno script postinstall esegua prisma generate e prisma migrate deploy sul server. Ogni piano bot include un database MySQL. Abbiamo provato il codice e i comandi qui sotto il 6 novembre 2026 con Prisma 7.10.1, discord.js 14 e Node.js 22, su MariaDB 10.11 con un account database configurato come il nostro (nessun permesso di creare database, 20 connessioni, limite di 120 secondi per le query), ma non con un vero login a Discord.

Prisma 7, non l'ultima versione di npm

Il 6 novembre 2026 il tag latest del pacchetto prisma su npm punta a una release candidate di Prisma 8 (8.0.0-rc.30), e il quickstart MySQL di Prisma è quello di Prisma 7: installa prisma@prev e @prisma/client@7. Per questo la guida fissa ogni pacchetto Prisma a ^7. Un semplice npm install prisma ti darebbe la versione 8.

Cosa ti serve

  • Un bot discord.js scritto in TypeScript. Il nostro tipo Node.js Bot esegue con tsx un file principale che termina in .ts, quindi non serve compilare nulla prima: Come eseguire un bot Discord in TypeScript.
  • Un piano bot PlayNHost con il tipo Node.js Bot. Ogni piano include un database.
  • Node.js e npm sul tuo computer, per scrivere la migrazione una volta.

1. Crea il database e le variabili

  1. Apri il server del tuo bot nel pannello, clicca su Database, poi su Nuovo database e Crea database.
  2. Si apre la pagina del nuovo database (più avanti, cliccalo in I tuoi database). Tienila aperta e, sotto Config pronta all’uso, scegli Generic URL in Config per: è la stringa di connessione mysql://... che serve alla riga di comando di Prisma.
  3. Apri la pagina Bot, il riquadro Ambiente, clicca su Incolla un file .env e incolla sei righe con i tuoi valori. Per DATABASE_URL, incolla la Generic URL esattamente come viene mostrata: le password dei nostri database possono contenere caratteri come @ e +, che Prisma richiede codificati in percentuale dentro un URL, e la Generic URL è già codificata.
    DB_HOST=your-host
    DB_PORT=3306
    DB_NAME=your-database
    DB_USER=your-username
    DB_PASSWORD=your-password
    DATABASE_URL=mysql://your-username:your-password@your-host:3306/your-database
  4. DB_PASSWORD e DATABASE_URL ricevono un badge Segreto: vengono salvate in sola scrittura. Clicca su Importa 6 variabili.

Il bot si collega con i cinque valori DB_, passati all'adapter uno per uno come nel quickstart di Prisma. DATABASE_URL serve solo ai comandi prisma eseguiti durante l'installazione.

2. I file del progetto

package.json

{
  "name": "my-discord-bot",
  "private": true,
  "type": "module",
  "scripts": {
    "postinstall": "prisma generate && prisma migrate deploy"
  },
  "dependencies": {
    "@prisma/adapter-mariadb": "^7",
    "@prisma/client": "^7",
    "discord.js": "^14"
  },
  "devDependencies": {
    "prisma": "^7"
  }
}

prisma7.config.ts (Prisma 7.10 e successivi usano questo nome, così non entra in conflitto con il prisma.config.ts di Prisma 8)

import { defineConfig } from "prisma/config";

export default defineConfig({
  schema: "prisma/schema.prisma",
  migrations: {
    path: "prisma/migrations",
  },
  datasource: {
    url: process.env.DATABASE_URL,
  },
});

prisma/schema.prisma

generator client {
  provider = "prisma-client"
  output   = "../generated/prisma"
}

datasource db {
  provider = "mysql"
}

model Warning {
  id        Int      @id @default(autoincrement())
  guildId   String   @db.VarChar(20)
  userId    String   @db.VarChar(20)
  reason    String   @db.VarChar(200)
  createdAt DateTime @default(now())

  @@index([guildId, userId])
}

index.ts

import { Client, Events, GatewayIntentBits, InteractionContextType, MessageFlags, REST, Routes, SlashCommandBuilder } from "discord.js";
import { PrismaMariaDb } from "@prisma/adapter-mariadb";
import { PrismaClient } from "./generated/prisma/client";

// One client for the whole bot. The values come from the Environment pane.
const adapter = new PrismaMariaDb({
  host: process.env.DB_HOST,
  port: Number(process.env.DB_PORT),
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  connectionLimit: 5,
});
const prisma = new PrismaClient({ adapter });

const commands = [
  new SlashCommandBuilder()
    .setName("warn")
    .setDescription("Warn a member and count their warnings")
    .setContexts(InteractionContextType.Guild)
    .addUserOption((o) => o.setName("user").setDescription("Who to warn").setRequired(true))
    .addStringOption((o) => o.setName("reason").setDescription("Why").setRequired(true).setMaxLength(200))
    .toJSON(),
];

const client = new Client({ intents: [GatewayIntentBits.Guilds] });

client.once(Events.ClientReady, async (c) => {
  await new REST().setToken(process.env.DISCORD_TOKEN!).put(Routes.applicationCommands(c.user.id), { body: commands });
  console.log(`Logged in as ${c.user.tag}`);
});

client.on(Events.InteractionCreate, async (interaction) => {
  if (!interaction.isChatInputCommand() || interaction.commandName !== "warn" || !interaction.guildId) return;
  const user = interaction.options.getUser("user", true);
  const reason = interaction.options.getString("reason", true);
  try {
    await prisma.warning.create({ data: { guildId: interaction.guildId, userId: user.id, reason } });
    const total = await prisma.warning.count({ where: { guildId: interaction.guildId, userId: user.id } });
    await interaction.reply(`${user} has ${total} warning(s).`);
  } catch (err) {
    console.error(err);
    if (!interaction.replied) await interaction.reply({ content: "Could not save the warning. Try again later.", flags: MessageFlags.Ephemeral }).catch(console.error);
  }
});

client.login(process.env.DISCORD_TOKEN);

setContexts(InteractionContextType.Guild) e il controllo !interaction.guildId tengono /warn fuori dai messaggi privati. Il try/catch è importante: senza, discord.js passa una query fallita al suo evento error, e quando nessuno lo ascolta Node.js ferma il bot.

3. Scrivi la prima migrazione sul tuo computer

Nella cartella del progetto sul tuo computer (su Windows, crea a mano le cartelle prisma\migrations\0_init invece di usare mkdir -p):

npm install --ignore-scripts
mkdir -p prisma/migrations/0_init
npx prisma migrate diff --from-empty --to-schema prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql

migrate diff confronta un database vuoto con il tuo schema e scrive l'SQL, senza collegarsi ad alcun database. --ignore-scripts salta il postinstall, che proverebbe a raggiungere un database. Il file inizia con -- CreateTable e CREATE TABLE `Warning`.

4. Carica e avvia

  1. In Files, carica package.json, prisma7.config.ts, index.ts e la cartella prisma con schema.prisma e migrations. Non caricare node_modules né generated: il server crea entrambe.
  2. Nella pagina Bot, riquadro Codice, imposta File di avvio su index.ts.
  3. Premi Avvia e apri Console. L'installazione esegue il tuo postinstall: vedi Generated Prisma Client (7.10.1), poi All migrations have been successfully applied., poi [PlayNHost] Starting your bot e Logged in as ....

La console mostra anche npm warn install-scripts 2 packages had install scripts blocked per prisma e @prisma/engines. La versione di npm nella nostra immagine Node.js 22 blocca gli script di installazione delle dipendenze se non sono consentiti. Il tuo postinstall gira comunque, e nel nostro test Prisma ha generato, migrato e interrogato il database senza quegli script.

Perché non prisma migrate dev?

prisma migrate dev crea prima un database shadow temporaneo per verificare le tue migrazioni. L'utente database del tuo bot può lavorare nel proprio database ma non può crearne di nuovi, quindi sui nostri server si ferma con:

Prisma Migrate could not create the shadow database. Please make sure the database user has permission to create databases. Read more about the shadow database (and workarounds) at https://pris.ly/d/migrate-shadow

Original error: Error code: P1010

User was denied access on the database `prisma_migrate_shadow_db_...`

prisma migrate deploy applica solo i file di migrazione e non richiede un database shadow, ed è per questo che il postinstall lo usa. Non puoi nemmeno puntare migrate dev al database del bot dal tuo computer: il database accetta solo connessioni dai server PlayNHost e da phpMyAdmin.

Modificare lo schema in seguito

  1. Sul tuo computer, esegui npx prisma migrate dev --name più un nome per la modifica, su un MySQL o MariaDB tuo, per esempio uno in Docker: imposta DATABASE_URL nel terminale su quel database, perché prisma7.config.ts la legge dall'ambiente. Scrive una nuova cartella in prisma/migrations.
  2. Carica la nuova cartella di migrazione e il schema.prisma modificato.
  3. Il server esegue npm install, e con esso il tuo postinstall, solo quando cambiano package.json, package-lock.json o la versione di Node.js, quando manca node_modules, o al primo avvio a più di un giorno dall'ultima installazione. Per applicare subito la migrazione, modifica package.json (per esempio il suo version) o elimina la cartella node_modules in Files, poi riavvia.

Memoria: l'installazione è la parte pesante

Abbiamo installato questo progetto da zero in un container limitato a 512 MB, come il nostro piano bot più piccolo. L'installazione, con prisma generate e prisma migrate deploy, ha richiesto 41 secondi e ha raggiunto un picco di 386 MB di memoria (cache dei file esclusa) in una esecuzione e di 417 MB in una seconda, senza alcun kill per memoria esaurita in nessuna delle due. Sta nel piano da 512 MB con meno di 100 MB di margine, quindi un progetto più grande o più pacchetti potrebbero superarlo. La stessa installazione senza Prisma (solo discord.js e mysql2) ha raggiunto un picco di 147 MB.

Limiti ed errori

  • 20 connessioni contemporanee per utente database, tra tutti i processi che usano lo stesso login. Tieni connectionLimit basso; 5 sono più che sufficienti per un bot.
  • Una query che dura più di 120 secondi viene fermata, con l'errore 1969 Query execution was interrupted (max_statement_time exceeded).
  • 500 MB per database: 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.
  • I problemi di connessione hanno le stesse cause che con mysql2 (password sbagliata, host o porta sbagliati, una variabile mancante in Ambiente, connessione dal tuo computer), ma i messaggi sono diversi: l'adapter MariaDB usa il driver mariadb, non mysql2, e non abbiamo registrato i suoi messaggi. Le cause sono elencate in Come usare un database MySQL con un bot discord.js.

Preferisci SQL semplice con mysql2 o aiomysql? discord.js (mysql2), discord.py (aiomysql). La panoramica: Come usare un database con il tuo bot Discord. Ti serve un server bot con database incluso? Guarda i piani bot.

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

ULTIMI ARTICOLI