NOUVEAU 📢 Offre de lancement limitée : jusqu'à 70 % de remise sur votre premier mois, pour tous les jeux !Voir les offres

Comment utiliser une base de données MySQL avec un bot aiogram (aiomysql)

Hébergement de bots TelegramUpdated Nov 6, 202613 min read

Réponse courte. Ajoutez aiomysql à votre bot aiogram 3, ouvrez un seul pool avec autocommit=True avant le début du polling et transmettez-le à vos handlers avec dp.start_polling(bot, pool=pool) : aiogram le passe à chaque handler qui a un paramètre pool. Utilisez %s comme marqueurs et stockez les IDs Telegram en BIGINT, pas en INT. Chez PlayNHost, chaque offre de bot inclut une base 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 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 aiogram 3.31.0, aiomysql 0.3.2 et Python 3.12, sur MariaDB 10.11, avec un compte de base de données configuré comme les nôtres (20 connexions, limite de requête de 120 secondes) et un substitut du serveur Bot API de Telegram : 8 commandes en entrée, 8 réponses en sortie, les notes enregistrées dans la base. Une vraie connexion à Telegram ne faisait pas partie du test.

Ce qu’il vous faut

1. Créer la base de données

  1. Ouvrez votre serveur de bot dans le panel et cliquez sur Bases de données.
  2. Cliquez sur Nouvelle base de données. Un Libellé est facultatif ; Sera créée sous le nom indique le nom complet. Cliquez sur Créer une base de données.
  3. 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. Renseigner les informations dans Environnement

  1. Ouvrez la page Bot, volet Environnement, et cliquez sur Coller un fichier .env.
  2. Collez ces cinq lignes avec les valeurs de la carte Connexion :
    DB_HOST=your-host
    DB_PORT=3306
    DB_NAME=your-database
    DB_USER=your-username
    DB_PASSWORD=your-password
  3. DB_PASSWORD reçoit un badge Secret : elle est enregistrée en écriture seule et n’est plus jamais affichée. Cliquez sur Importer 5 variables.

Utilisez le vrai port indiqué sur la carte Connexion. Le token du bot ne fait pas partie de ces lignes : le token que vous avez enregistré sur la page Bot, volet Telegram, arrive déjà dans votre code sous le nom BOT_TOKEN, le nom qu’utilisent les propres exemples d’aiogram (et sous les noms TELEGRAM_BOT_TOKEN, TOKEN, TELEGRAM_TOKEN et TELOXIDE_TOKEN). Si votre fichier .env contient une ligne de token, la boîte de dialogue l’ignore. Plus d’infos sur ce volet : Comment définir des variables d’environnement et des secrets pour votre bot Discord.

3. Le code

Un petit bot de notes : /note buy milk enregistre une note, /notes affiche vos cinq dernières.

requirements.txt

aiogram>=3,<4
aiomysql

bot.py

import asyncio
import logging
import os
import sys

import aiomysql
from aiogram import Bot, Dispatcher
from aiogram.filters import Command, CommandObject
from aiogram.types import Message

dp = Dispatcher()


@dp.message(Command("note"))
async def note(message: Message, command: CommandObject, pool: aiomysql.Pool) -> None:
    text = (command.args or "").strip()
    if not text:
        await message.answer("Write your note after the command, for example: /note buy milk")
        return
    if len(text) > 500:
        await message.answer("A note can be up to 500 characters.")
        return
    async with pool.acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute(
                "INSERT INTO notes (user_id, text) VALUES (%s, %s)",
                (message.from_user.id, text),
            )
    await message.answer("Saved. Send /notes to see your last five.")


@dp.message(Command("notes"))
async def notes(message: Message, pool: aiomysql.Pool) -> None:
    async with pool.acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute(
                "SELECT text FROM notes WHERE user_id = %s ORDER BY id DESC LIMIT 5",
                (message.from_user.id,),
            )
            rows = await cur.fetchall()
    if not rows:
        await message.answer("You have no notes yet.")
        return
    await message.answer("\n".join(f"- {text}" for (text,) in rows))


async def main() -> None:
    # One pool for the whole bot. The values come from the Environment pane.
    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 pool.acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute(
                "CREATE TABLE IF NOT EXISTS notes ("
                "id INT AUTO_INCREMENT PRIMARY KEY, "
                "user_id BIGINT NOT NULL, "
                "text VARCHAR(500) NOT NULL, "
                "created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, "
                "KEY user_id (user_id))"
            )
    print("Database ready")

    bot = Bot(os.environ["BOT_TOKEN"])
    try:
        # Every keyword passed here reaches the handlers that ask for it by name.
        await dp.start_polling(bot, pool=pool)
    finally:
        pool.close()
        await pool.wait_closed()


if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO, stream=sys.stdout)
    asyncio.run(main())

Ce qu’il fait : main() ouvre le pool, crée la table notes si elle manque et affiche Database ready avant que le bot demande des messages à Telegram. dp.start_polling(bot, pool=pool) est la façon propre à aiogram de partager un objet : chaque mot-clé supplémentaire que vous passez devient une donnée qu’aiogram transmet à tout handler ayant un paramètre de ce nom, donc note() et notes() reçoivent le même pool. Quand le bot s’arrête, le bloc finally ferme le pool.

Les marqueurs %s sont remplis par le driver, donc une note comme '); DROP TABLE notes; -- est stockée comme du texte brut. Dans notre test, elle a été enregistrée en ligne 2 et la table est restée. Ne construisez jamais le SQL avec une f-string.

Stockez les IDs Telegram en BIGINT

La documentation de la Bot API de Telegram indique qu’un ID d’utilisateur ou de chat « peut avoir plus de 32 bits significatifs » mais au plus 52, donc un entier de 64 bits suffit. Sa page sur les IDs donne les plages : les IDs d’utilisateur montent jusqu’à 1.099.511.627.775, tandis que les IDs de groupes, supergroupes et canaux sont négatifs. Les supergroupes et canaux vont de -1.000.000.000.001 à -1.997.852.516.352 (par exemple -1001234567890). Le type INT de MySQL s’arrête à 2.147.483.647. Dans notre test, avec le même mode SQL strict que celui de notre serveur de base de données, l’enregistrement de l’ID d’utilisateur 7.000.000.001 dans une colonne INT a échoué. aiomysql a levé :

pymysql.err.DataError: (1264, "Out of range value for column 'user_id' at row 1")

Une colonne BIGINT l’a enregistré, et -1001234567890 aussi. Utilisez un simple BIGINT, pas BIGINT UNSIGNED, pour que les IDs de chat tiennent aussi.

4. Lancez-le

  1. Téléversez bot.py et requirements.txt dans Fichiers.
  2. Appuyez sur Démarrer et ouvrez Console. Le démarrage installe les paquets de requirements.txt, puis affiche [PlayNHost] Starting your bot, Database ready et Run polling for bot @your_bot. Cette dernière ligne fait passer l’état dans Aperçu à En ligne sur Telegram.
  3. Dans Telegram, envoyez à votre bot /note buy milk, puis /notes. Pour voir les lignes, ouvrez la page de la base de données et cliquez sur Ouvrir dans phpMyAdmin.

À partir du deuxième démarrage, la console affiche aussi Warning: Table 'notes' already exists, avec devant le chemin du fichier cursors.py d’aiomysql. C’est la remarque de MariaDB pour CREATE TABLE IF NOT EXISTS, relayée par le driver. Rien n’est cassé.

Dans notre test, le substitut de Telegram a envoyé ces commandes et reçu ces réponses :

EnvoyéRéponse
/note buy milkSaved. Send /notes to see your last five.
/noteWrite your note after the command, for example: /note buy milk
/note et 501 caractèresA note can be up to 500 characters.
/notesLes notes enregistrées, les plus récentes d’abord
/notes d’un deuxième utilisateurYou have no notes yet.

Beaucoup de messages à la fois

aiogram traite chaque mise à jour entrante comme sa propre tâche, donc plusieurs commandes peuvent exécuter leurs requêtes en même temps. Dans notre test, 4 commandes arrivées ensemble ont chacune été traitées en environ 50 ms. maxsize=5 limite le pool à 5 connexions ; une sixième requête attend qu’une connexion se libère au lieu d’en ouvrir une autre. Après le test, le bot gardait 2 connexions ouvertes.

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 au 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. Soit passez autocommit=True à create_pool, comme ci-dessus, soit appelez await conn.commit() après vos écritures.

Une requête en échec n’arrête pas le bot

Dans notre test, nous avons supprimé la table pendant que le bot tournait et envoyé /notes. aiogram a journalisé l’erreur avec une trace se terminant par pymysql.err.ProgrammingError: (1146, "Table '...notes' doesn't exist"), n’a envoyé aucune réponse pour cette commande et a continué de tourner : une fois la table de retour, le /note suivant a été enregistré. La personne qui a envoyé la commande ne voit rien, donc si une requête peut échouer, interceptez l’erreur dans le handler et répondez par un court message.

Une nuit calme ne casse pas le pool

Notre serveur de base de données ferme une connexion restée inactive pendant 8 heures. Un bot qui ne reçoit aucun message aussi longtemps, pendant la nuit par exemple, trouve ses connexions du pool fermées. aiomysql le vérifie quand un handler demande une connexion et en ouvre une nouvelle à la place de celle qui est fermée. Nous l’avons testé avec la limite d’inactivité abaissée à 5 secondes : après 7 secondes de calme, le /note suivant a été enregistré sans erreur.

Les limites qui comptent pour votre pool

  • 20 connexions à la fois par utilisateur de base de données. Chaque 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 arrêtée. MariaDB y met fin avec l’erreur 1969, Query execution was interrupted (max_statement_time exceeded). Dans un test précédent, sur un compte configuré de la même façon, cela est arrivé au bout de 120,03 secondes. Les requêtes d’un bot prennent normalement quelques 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 sens

Voici les erreurs qu’aiomysql a données dans notre test, écrites comme elles terminent une trace dans la console (elles viennent de PyMySQL, qu’aiomysql utilise en dessous) :

  • pymysql.err.OperationalError: (1045, "Access denied for user ...") : mauvais DB_USER ou mauvais DB_PASSWORD. 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 n’accepte que les connexions des serveurs PlayNHost et de phpMyAdmin, c’est donc aussi ce que vous obtenez depuis votre propre ordinateur.
  • pymysql.err.OperationalError: (1226, ... 'max_user_connections' ...) : trop de connexions ouvertes, voir les limites ci-dessus. Par exemple une deuxième copie du bot, ou un pool ouvert pour chaque message.
  • pymysql.err.DataError: (1264, "Out of range value for column 'user_id' at row 1") : une colonne d’ID est de type INT. Passez-la en BIGINT.
  • pymysql.err.ProgrammingError: (1146, "Table '...' doesn't exist") : la table est absente. Le code ci-dessus la crée au démarrage ; si vous l’avez créée à la main, vérifiez son nom.

Une variable manquante dans Environnement arrête le bot avant sa connexion, avec KeyError: 'DB_HOST' ou le nom de la variable manquante, car le code lit chaque valeur avec os.environ[...]. Ajoutez-la, puis redémarrez le bot : les variables s’appliquent au prochain démarrage.

Un mauvais token apparaît après la partie base de données. Avec notre faux token contre le vrai Telegram, le bot a affiché Database ready, puis s’est arrêté avec aiogram.exceptions.TelegramUnauthorizedError: Telegram server says - Unauthorized. Copiez à nouveau le token depuis @BotFather et collez-le sur la page Bot, volet Telegram. Plus d’erreurs Telegram : Corriger l’erreur 409 Conflict d’un bot Telegram.

La mémoire utilisée

Dans notre test, le bot en marche a utilisé 174 MB de mémoire (résidente) après avoir répondu aux 8 commandes, avec son pool ouvert, dans un conteneur limité à 512 MB comme notre plus petite offre de bot. L’essentiel vient d’aiogram lui-même : lors de notre précédent test d’hébergement, aiogram seul a mesuré 173 MB (ce bot s’est arrêté sur un token refusé, avant de traiter un message, donc les deux chiffres sont proches mais la comparaison n’est pas exacte). L’installation d’aiogram et d’aiomysql avec pip à partir de zéro a atteint 163 MB, cache de fichiers compris. Cela laisse de la place pour votre propre code sur la plus petite offre. Le guide d’hébergement compare les bibliothèques : python-telegram-bot vs aiogram sur PlayNHost.

La même chose avec une autre bibliothèque

Vous voulez un serveur pour votre bot Telegram avec une base de données incluse ? Voir les offres de bot Telegram.

Votre bot est hébergé ailleurs ? Transférez-le chez nous

NOS DERNIERS ARTICLES