Réponse courte. Ajoutez aiomysql à votre bot discord.py, créez un seul pool dans setup_hook avec autocommit=True, et faites passer chaque requête par lui avec des marqueurs %s. Sans autocommit=True (ou un commit() après chaque écriture), aiomysql n’enregistre pas vos INSERT. 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.py 2.7.1, aiomysql 0.3.2 et Python 3.12, 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 la commande /warn, mais pas une vraie connexion à Discord.
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 Python (aiomysql) 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 :
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"])
Ce qu’il fait : discord.py exécute setup_hook une seule fois, pendant la connexion et avant l’arrivée de tout événement, si bien que le pool et la table warnings existent avant l’arrivée de la première commande. Il enregistre ensuite /warn auprès de Discord. @app_commands.guild_only() tient la commande à l’écart des messages privés, où il n’y a aucun serveur pour enregistrer l’avertissement. Les ID Discord tiennent dans BIGINT UNSIGNED. Les marqueurs %s sont remplis par le pilote, si bien qu’un motif comme '); DROP TABLE warnings; -- est enregistré comme du texte brut. Ne construisez jamais le SQL avec une f-string.
4. Lancer le bot
Envoyez bot.py et requirements.txt dans Fichiers.
Appuyez sur Démarrer et ouvrez Console. Le démarrage installe les paquets de requirements.txt, puis affiche [PlayNHost] Starting your bot et Database ready.
Dans Discord, tapez /warn. Pour voir les lignes, ouvrez la page de la base et cliquez sur Ouvrir dans phpMyAdmin.
Le piège de l’autocommit
aiomysql ouvre les connexions avec l’autocommit désactivé. Un INSERT reste alors dans une transaction ouverte. Quand la connexion retourne dans le pool avec cette transaction encore ouverte, aiomysql la ferme, et MariaDB jette la ligne non validée. Dans notre test, une ligne insérée sur un pool sans autocommit=True a été vue par 0 autre connexion. Passez autocommit=True à create_pool, comme ci-dessus, ou appelez await conn.commit() après vos écritures.
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. La connexion 21 est refusée avec (1226, "User '...' has exceeded the 'max_user_connections' resource (current value: 20)"). maxsize=5 garde le bot bien en dessous.
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 erreurs exactes qu’aiomysql a données dans notre test (elles viennent de PyMySQL, qu’aiomysql utilise en dessous) :
pymysql.err.OperationalError (1045, "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.
pymysql.err.OperationalError (2003, "Can't connect to MySQL server on ...") : hôte ou port incorrect, ou connexion depuis l’extérieur de PlayNHost. La base de données n’accepte que les connexions des serveurs PlayNHost et de phpMyAdmin, c’est donc aussi ce que vous obtenez depuis votre propre ordinateur.
(1226, ... 'max_user_connections' ...) : trop de connexions ouvertes, voir les limites ci-dessus.
Une variable absente de Environnement arrête le bot avant sa connexion, avec KeyError: 'DB_HOST' ou le nom de celle qui manque, car le code lit chaque valeur avec os.environ[...]. Ajoutez-la, puis redémarrez le bot : les variables s’appliquent au prochain démarrage.
Installer discord.py et aiomysql avec pip de zéro a atteint un pic de 78 MB de mémoire dans notre test, dans un conteneur limité à 512 MB comme notre plus petite offre de bot. La mémoire dont le bot en marche a besoin dépend surtout du nombre de serveurs où il se trouve : 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é