YENİ 📢 Sınırlı lansman teklifi: Tüm oyunlarda ilk aya %70'e varan indirim!Paketleri görün

discord.py botuyla MySQL veritabanı nasıl kullanılır (aiomysql)

Discord botlarıUpdated Nov 6, 20267 min read

Kısa cevap. discord.py botunuza aiomysql ekleyin, setup_hook içinde autocommit=True ile tek bir havuz oluşturun ve her sorguyu %s yer tutucularıyla bu havuz üzerinden çalıştırın. autocommit=True olmadan (ya da her yazmadan sonra bir commit() olmadan) aiomysql INSERT’lerinizi kaydetmez. PlayNHost’ta her bot planı bir MySQL veritabanı içerir: onu Veritabanları sayfasında oluşturun, bilgilerini Ortam bölmesine yapıştırın, aşağıdaki kod olduğu gibi çalışır. Veritabanı, PlayNHost sunucularınızdan ve phpMyAdmin’den gelen bağlantıları kabul eder; kendi bilgisayarınızdan gelenleri kabul etmez. Bu kodu 6 Kasım 2026’da discord.py 2.7.1, aiomysql 0.3.2 ve Python 3.12 ile, bizimki gibi ayarlanmış bir veritabanı hesabıyla (20 bağlantı, 120 saniyelik sorgu sınırı) MariaDB 10.11 üzerinde denedik: başlatma, tablo ve /warn komutu, ancak gerçek bir Discord girişi değil.

Neye ihtiyacınız var

1. Veritabanını oluşturun

  1. Bot sunucunuzu panelde açın ve Veritabanları seçeneğine tıklayın.
  2. Yeni veritabanı seçeneğine tıklayın. Etiket alanı isteğe bağlıdır; Şu adla oluşturulacak: alanı tam adı gösterir. Veritabanı oluştur düğmesine tıklayın.
  3. Yeni veritabanının sayfası açılır (daha sonra Veritabanlarınız bölümünden ona tıklayın). Bağlantı kartında Sunucu adresi, Port, Veritabanı, Kullanıcı Adı ve Şifre görünür. Hazır yapılandırma altında, Şunun için yapılandırma içinde aynı değerlerin doldurulduğu bir Python (aiomysql) parçası bulunur.

2. Bilgileri Ortam bölümüne girin

  1. Bot sayfasını, Ortam bölmesini açın ve .env dosyası yapıştır düğmesine tıklayın.
  2. Bağlantı kartındaki değerlerle şu beş satırı yapıştırın:
    DB_HOST=your-host
    DB_PORT=3306
    DB_NAME=your-database
    DB_USER=your-username
    DB_PASSWORD=your-password
  3. DB_PASSWORD için bir Gizli rozeti çıkar: yalnızca yazılabilir olarak kaydedilir ve bir daha gösterilmez. 5 değişkeni içe aktar düğmesine tıklayın.

Bağlantı kartındaki gerçek portu kullanın. Kodunuz değerleri os.environ ile okur, bu yüzden şifre botunuzun dosyalarında asla durmaz. Bu bölme hakkında daha fazlası: Discord botunuz için ortam değişkenleri ve gizli değerler nasıl ayarlanır.

3. Kod

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"])

Ne yapar: discord.py setup_hook işlevini giriş sırasında, herhangi bir olay gelmeden önce bir kez çalıştırır; böylece havuz ve warnings tablosu ilk komut gelmeden önce hazır olur. Sonra /warn komutunu Discord’a kaydeder. @app_commands.guild_only(), komutu uyarının kaydedileceği bir sunucunun olmadığı özel mesajların dışında tutar. Discord kimlikleri BIGINT UNSIGNED içine sığar. %s yer tutucularını sürücü doldurur, bu yüzden '); DROP TABLE warnings; -- gibi bir neden düz metin olarak kaydedilir. SQL’i asla bir f-string ile oluşturmayın.

4. Çalıştırın

  1. bot.py ve requirements.txt dosyalarını Dosyalar bölümünden yükleyin.
  2. Başlat düğmesine basın ve Konsol bölümünü açın. Başlatma, requirements.txt içindeki paketleri kurar, ardından [PlayNHost] Starting your bot ve Database ready görünür.
  3. Discord’da /warn yazın. Satırlara bakmak için veritabanının sayfasını açın ve phpMyAdmin’de aç düğmesine tıklayın.

autocommit tuzağı

aiomysql bağlantıları autocommit kapalı olarak açar. Bu durumda bir INSERT açık bir işlemin içinde kalır. Bağlantı o işlem hâlâ açıkken havuza döndüğünde aiomysql onu kapatır ve MariaDB onaylanmamış satırı atar. Testimizde, autocommit=True olmayan bir havuzda eklenen satırı 0 başka bağlantı gördü. Ya yukarıdaki gibi autocommit=True değerini create_pool işlevine verin ya da yazmalarınızdan sonra await conn.commit() çağırın.

Havuzunuz için önemli sınırlar

  • Veritabanı kullanıcısı başına aynı anda 20 bağlantı. Aynı girişi kullanan her işlem sayılır. 21. bağlantı (1226, "User '...' has exceeded the 'max_user_connections' resource (current value: 20)") ile reddedilir. maxsize=5 botu bunun epey altında tutar.
  • 120 saniyeden uzun süren bir sorgu durdurulur. MariaDB onu 1969 hatasıyla, Query execution was interrupted (max_statement_time exceeded), sonlandırır. Testimizde bu 120.03 saniye sonra oldu. Bir botun sorguları normalde milisaniyeler sürer, yani bu yalnızca kontrolden çıkmış bir sorguyu etkiler.
  • Veritabanı başına 500 MB. Veritabanları sayfası ne kadarının kullanıldığını gösterir. 500 MB’a gelince, siz satırları silene kadar yazma işlemleri durdurulur.
  • Sunucu yedekleri veritabanını içermez. Zaman zaman phpMyAdmin’den dışa aktarın.

Hatalar ve ne anlama geldikleri

Bunlar aiomysql’in testimizde verdiği tam hatalardır (aiomysql’in altta kullandığı PyMySQL’den gelirler):

  • pymysql.err.OperationalError (1045, "Access denied for user ..."): yanlış DB_USER ya da DB_PASSWORD. Bağlantı kartında Şifreyi sıfırla işleminden sonra eski şifre hemen çalışmaz: DB_PASSWORD değerini değiştirin ve botu yeniden başlatın.
  • pymysql.err.OperationalError (2003, "Can't connect to MySQL server on ..."): yanlış sunucu adresi ya da port, ya da PlayNHost dışından bir bağlantı. Veritabanı yalnızca PlayNHost sunucularından ve phpMyAdmin’den gelen bağlantıları kabul eder, bu yüzden kendi bilgisayarınızda da bunu alırsınız.
  • (1226, ... 'max_user_connections' ...): çok fazla bağlantı açık, yukarıdaki sınırlara bakın.

Ortam içinde eksik bir değişken botu bağlanmadan önce KeyError: 'DB_HOST' ya da eksik olanın adıyla durdurur, çünkü kod her değeri os.environ[...] ile okur. Onu ekleyin, sonra botu yeniden başlatın: değişkenler bir sonraki başlatmada geçerli olur.

Daha fazla bot hatası: Sık görülen Discord bot hataları ve ne anlama geldikleri.

Ne kadar bellek ekler

discord.py ve aiomysql’i pip ile sıfırdan kurmak testimizde en çok 78 MB bellek kullandı, en küçük bot planımız gibi 512 MB ile sınırlı bir konteynerde. Çalışan botun ne kadar belleğe ihtiyaç duyduğu çoğunlukla kaç sunucuda olduğuna bağlıdır: Bir Discord botunun ne kadar RAM’e ihtiyacı var?

Aynısı JavaScript’te ya da Prisma ile

Veritabanı dahil bir bot sunucusu mu lazım? Bot planlarına bakın.

Botun başka bir yerde mi? Bize taşı

EN YENİ BLOG YAZILARIMIZ