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

discord.js botuyla MySQL veritabanı nasıl kullanılır (mysql2)

Discord botlarıUpdated Nov 6, 20267 min read

Kısa cevap. discord.js botunuza mysql2 ekleyin, bot başlarken ortam değişkenlerinden tek bir bağlantı havuzu oluşturun ve her sorguyu ? yer tutucularıyla bu havuz üzerinden çalıştırın. 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.js 14.28.1, mysql2 3.24.6 ve Node.js 22 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 işleyicisi, 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 Node.js (mysql2) 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. Şifreyi kodunuzun dışında tutmak, onun asla bir dosyaya ya da Git deposuna düşmemesi demektir. 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

package.json

{
  "name": "my-discord-bot",
  "private": true,
  "main": "index.js",
  "dependencies": {
    "discord.js": "^14",
    "mysql2": "^3"
  }
}

index.js

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);
});

Ne yapar: bot başlarken warnings tablosu yoksa onu oluşturur, Database ready yazdırır, sonra giriş yapar. /warn bir uyarıyı kaydeder ve üyenin toplamıyla cevap verir. discord.js, Discord kimliklerini dize olarak verir, çünkü bunlar bir JavaScript sayısı için çok büyüktür; bu yüzden metin olarak saklanırlar. ? yer tutucuları üyenin metnini SQL’den ayrı olarak veritabanına gönderir, bu yüzden '); DROP TABLE warnings; -- gibi bir neden düz metin olarak kaydedilir.

İki satır botu ayakta tutar. setContexts(InteractionContextType.Guild) ve !interaction.guildId denetimi, uyarının kaydedileceği bir sunucunun olmadığı özel mesajda /warn kullanımını engeller. try/catch bloğu, bir sorgu başarısız olduğunda kısa bir özel mesajla cevap verir. O olmadan discord.js hatayı kendi error olayına iletir ve orada kimse dinlemiyorsa Node.js botu durdurur. Testimizde tabloyu sildik ve /warn çalıştırdık: bot ER_NO_SUCH_TABLE kaydetti, Could not save the warning. Try again later. diye cevap verdi ve çalışmaya devam etti.

4. Çalıştırın

  1. index.js ve package.json dosyalarını Dosyalar bölümünden yükleyin. node_modules klasörünü yüklemeyin.
  2. Başlat düğmesine basın ve Konsol bölümünü açın. Başlatma paketleri kurar, ardından [PlayNHost] Starting your bot, Database ready ve Logged in as ... 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.

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: botunuz, onun ikinci bir kopyası, bir panel. 21. bağlantı ER_USER_LIMIT_REACHED ile reddedilir. Testimizde connectionLimit: 30 olan bir havuz, 30 sorgu aynı anda çalışır çalışmaz bu hatayla başarısız oldu. 5’lik bir havuz asla 5’ten fazlasını açmaz: fazla sorgular boş bir bağlantıyı bekler.
  • 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 mysql2’nin testimizde verdiği tam mesajlardır:

  • ER_ACCESS_DENIED_ERROR ... 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.
  • ECONNREFUSED: o sunucu adresinde ve portta bağlantıyı hiçbir şey kabul etmedi. DB_HOST ve DB_PORT değerlerini kontrol edin. Eksik bir DB_HOST da buraya düşer, çünkü mysql2 o zaman hiçbir veritabanının çalışmadığı localhost adresine bağlanır: değişken Ortam içinde yok ya da eklendikten sonra bot yeniden başlatılmadı.
  • ENOTFOUND: DB_HOST yanlış yazılmış, yani bu ad yok.
  • ETIMEDOUT: 10 saniye içinde hiçbir şey cevap vermedi, bu mysql2’nin varsayılan bekleme süresidir. Mesaj ne olursa olsun, kendi bilgisayarınızdan yapılan bağlantı başarısız olur: veritabanı yalnızca PlayNHost sunucularından ve phpMyAdmin’den gelen bağlantıları kabul eder.
  • ER_USER_LIMIT_REACHED ... has exceeded the 'max_user_connections' resource (current value: 20): çok fazla bağlantı açık, yukarıdaki sınırlara bakın. Genellikle her komut için açılan ve hiç kapatılmayan yeni bir bağlantı ya da botun ikinci bir kopyasıdır.

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

Ne kadar bellek ekler

discord.js ve mysql2’yi sıfırdan kurmak testimizde en çok 147 MB bellek kullandı (dosya önbelleği sayılmadan), en küçük bot planımız gibi 512 MB ile sınırlı bir konteynerde. Başlatmadan Discord’un test jetonumuzu reddettiği ana kadar bot en fazla 31 MB kullandı; tabloyu kurmuştu ama hiç giriş yapmamıştı. Giriş yapmış ve çok sayıda sunucuda olan bir bot daha fazlasını kullanır: Bir Discord botunun ne kadar RAM’e ihtiyacı var?

Aynısı Python’da 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