Réponse courte. Ajoutez mysql2 à votre bot discord.js, créez un seul pool de connexions à partir des variables d’environnement au démarrage du bot, et faites passer chaque requête par lui avec des marqueurs ?. Chez PlayNHost, chaque offre de bot inclut une base de données MySQL : créez-la sur la page Bases de données, collez ses informations dans le volet Environnement, et le code ci-dessous fonctionne tel quel. La base de données accepte les connexions de vos serveurs PlayNHost et de phpMyAdmin, pas celles de votre propre ordinateur. Nous avons testé ce code le 6 novembre 2026 avec discord.js 14.28.1, mysql2 3.24.6 et Node.js 22, sur MariaDB 10.11 avec un compte de base de données configuré comme le nôtre (20 connexions, limite de requête de 120 secondes) : le démarrage, la table et le gestionnaire de /warn, mais pas une vraie connexion à Discord.
Une offre de bot PlayNHost de type Node.js Bot. Chaque offre inclut une base de données.
1. Créer la base de données
Ouvrez votre serveur de bot dans le panel et cliquez sur Bases de données.
Cliquez sur Nouvelle base de données. Le Libellé est facultatif ; Sera créée sous le nom affiche le nom complet. Cliquez sur Créer une base de données.
La page de la nouvelle base s’ouvre (plus tard, cliquez dessus dans Vos bases de données). Sa carte Connexion affiche Hôte, Port, Base de données, Nom d’utilisateur et Mot de passe. Sous Config prête à l’emploi, Config pour propose un extrait Node.js (mysql2) avec les mêmes valeurs déjà remplies.
2. Enregistrer les identifiants dans Environnement
Ouvrez la page Bot, le volet Environnement, et cliquez sur Coller un fichier .env.
Collez ces cinq lignes avec les valeurs de la carte Connexion :
const { Client, Events, GatewayIntentBits, InteractionContextType, MessageFlags, REST, Routes, SlashCommandBuilder } = require('discord.js');
const mysql = require('mysql2/promise');
// One pool for the whole bot. The values come from the Environment pane.
const pool = mysql.createPool({
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 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 () => {
await new REST().setToken(process.env.DISCORD_TOKEN).put(Routes.applicationCommands(client.user.id), { body: commands });
console.log(`Logged in as ${client.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 pool.execute('INSERT INTO warnings (guild_id, user_id, reason) VALUES (?, ?, ?)', [interaction.guildId, user.id, reason]);
const [rows] = await pool.execute('SELECT COUNT(*) AS total FROM warnings WHERE guild_id = ? AND user_id = ?', [interaction.guildId, user.id]);
await interaction.reply(`${user} has ${rows[0].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);
}
});
async function main() {
await pool.query(`CREATE TABLE IF NOT EXISTS warnings (
id INT AUTO_INCREMENT PRIMARY KEY,
guild_id VARCHAR(20) NOT NULL,
user_id VARCHAR(20) NOT NULL,
reason VARCHAR(200) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY guild_user (guild_id, user_id)
)`);
console.log('Database ready');
await client.login(process.env.DISCORD_TOKEN);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
Ce qu’il fait : au démarrage, le bot crée la table warnings si elle manque, affiche Database ready, puis se connecte. /warn enregistre un avertissement et répond avec le total du membre. discord.js fournit les ID Discord sous forme de chaînes, car ils sont trop grands pour un nombre JavaScript, ils sont donc stockés comme du texte. Les marqueurs ? envoient le texte du membre à la base séparément du SQL, si bien qu’un motif comme '); DROP TABLE warnings; -- est enregistré comme du texte brut.
Deux lignes gardent le bot en vie. setContexts(InteractionContextType.Guild) et la vérification !interaction.guildId bloquent /warn en message privé, où il n’y a aucun serveur pour enregistrer l’avertissement. Le try/catch répond par un court message privé quand une requête échoue. Sans lui, discord.js transmet l’erreur à son événement error, et si personne n’écoute, Node.js arrête le bot. Dans notre test, nous avons supprimé la table et lancé /warn : le bot a journalisé ER_NO_SUCH_TABLE, a répondu Could not save the warning. Try again later. et a continué à tourner.
4. Lancer le bot
Envoyez index.js et package.json dans Fichiers. N’envoyez pas node_modules.
Appuyez sur Démarrer et ouvrez Console. Le démarrage installe les paquets, puis affiche [PlayNHost] Starting your bot, Database ready et Logged in as ....
Dans Discord, tapez /warn. Pour voir les lignes, ouvrez la page de la base et cliquez sur Ouvrir dans phpMyAdmin.
Les limites qui comptent pour votre pool
20 connexions simultanées par utilisateur de base de données. Tout processus qui utilise le même identifiant compte : votre bot, une deuxième copie, un tableau de bord. La connexion 21 est refusée avec ER_USER_LIMIT_REACHED. Dans notre test, un pool avec connectionLimit: 30 a échoué avec cette erreur dès que 30 requêtes ont tourné en même temps. Un pool de 5 n’ouvre jamais plus de 5 connexions : les requêtes en trop attendent une connexion libre.
Une requête qui dure plus de 120 secondes est interrompue. MariaDB y met fin avec l’erreur 1969, Query execution was interrupted (max_statement_time exceeded). Dans notre test, cela est arrivé après 120.03 secondes. Les requêtes d’un bot prennent normalement des millisecondes, donc cela ne touche qu’une requête qui s’emballe.
500 MB par base de données. La page Bases de données indique l’espace utilisé. À 500 MB, les écritures sont bloquées jusqu’à ce que vous supprimiez des lignes.
Les sauvegardes du serveur n’incluent pas la base de données. Exportez-la de temps en temps depuis phpMyAdmin.
Les erreurs et leur signification
Voici les messages exacts que mysql2 a donnés dans notre test :
ER_ACCESS_DENIED_ERROR ... Access denied for user : DB_USER ou DB_PASSWORD incorrect. Après Réinitialiser le mot de passe sur la carte Connexion, l’ancien mot de passe cesse de fonctionner immédiatement : remplacez DB_PASSWORD et redémarrez le bot.
ECONNREFUSED : rien n’a accepté la connexion à cet hôte et ce port. Vérifiez DB_HOST et DB_PORT. Un DB_HOST manquant aboutit aussi ici, car mysql2 se connecte alors à localhost, où aucune base ne tourne : la variable manque dans Environnement, ou le bot n’a pas été redémarré après son ajout.
ENOTFOUND : DB_HOST est mal orthographié, donc le nom n’existe pas.
ETIMEDOUT : rien n’a répondu en 10 secondes, l’attente par défaut de mysql2. Quel que soit le message, une connexion depuis votre propre ordinateur échoue : la base de données n’accepte que les connexions des serveurs PlayNHost et de phpMyAdmin.
ER_USER_LIMIT_REACHED ... has exceeded the 'max_user_connections' resource (current value: 20) : trop de connexions ouvertes, voir les limites ci-dessus. En général, une nouvelle connexion par commande qui n’est jamais fermée, ou une deuxième copie du bot.
Installer discord.js et mysql2 de zéro a atteint un pic de 147 MB de mémoire (cache de fichiers non compté) dans notre test, dans un conteneur limité à 512 MB comme notre plus petite offre de bot. Du démarrage jusqu’au refus de notre jeton de test par Discord, le bot a utilisé 31 MB au maximum ; il avait créé la table mais ne s’était jamais connecté. Un bot connecté et présent sur de nombreux serveurs en utilise davantage : De combien de RAM un bot Discord a-t-il besoin ?
Nous utilisons des cookies pour faire fonctionner le site, comprendre son utilisation et mesurer notre marketing. Vous pouvez tout accepter, accepter uniquement les cookies essentiels ou choisir par catégorie.Nous utilisons des cookies pour faire fonctionner le site, comprendre son utilisation et mesurer notre marketing. Ils sont activés par défaut ici. Vous pouvez désactiver ce que vous ne souhaitez pas.Lire notre politique de confidentialité