Connexion et utilisation de MySQL Node.js

MySQL est l'une des bases de données relationnelles open source les plus populaires, et Node.js est un environnement d'exécution JavaScript basé sur le moteur Chrome V8. Combiner les deux vous permet de créer des services backend puissants.

Pourquoi choisir MySQL + Node.js ?

  • MySQL offre un stockage et une gestion fiables des données
  • Le modèle d'E/S non bloquant de Node.js convient aux opérations de base de données
  • Développement full-stack en JavaScript (en utilisant le même langage pour le frontend et le backend)
  • Le riche écosystème npm propose de nombreux paquets liés à MySQL

Installation des dépendances requises

Avant de commencer, nous devons installer lemysql2paquet, qui est un choix populaire pour se connecter à MySQL dans Node.js.

npm install mysql2

Pourquoi choisir mysql2 plutôt que mysql ?

  • Meilleures performances
  • Prend en charge l'API Promise
  • Prend en charge les requêtes préparées
  • Maintenance active

Établissement de la connexion à la base de données

Configuration de connexion de base

Exemple

const mysql = require('mysql2');

// Créer un pool de connexions (recommandé pour la production)
const pool = mysql.createPool({
  host: 'localhost',     // Adresse du serveur de base de données
  user: 'root',          // Nom d'utilisateur de la base de données
  password: 'password',  // Mot de passe de la base de données
  database: 'test_db',   // Nom de la base de données à laquelle se connecter
  waitForConnections: true,
  connectionLimit: 10,   // Nombre maximum de connexions dans le pool
  queueLimit: 0
});

// Obtenir une connexion basée sur les promesses
const promisePool = pool.promise();

Pool de connexions vs connexion unique

Avantages d'un pool de connexions :

  • Réutiliser les connexions, réduire la surcharge
  • Gérer automatiquement le cycle de vie des connexions
  • Éviter les fuites de connexions
  • Meilleures performances

Scénarios adaptés à une connexion unique :

  • Scripts simples
  • Environnement de test
  • Applications à faible concurrence

Effectuer des opérations CRUD de base

Interroger des données (SELECT)

Exemple

async function getUsers() {
  try {
    const [rows, fields] = await promisePool.query('SELECT * FROM users');
    console.log(lignes);
    return rows;
  } catch (err) {
    console.error('Erreur de requête :', err);
    throw err;
  }
}

Insertion de données (INSERT)

Exemple

async function addUser(user) {
  try {
    const [result] = await promisePool.query(
      'INSERT INTO users (name, email) VALUES (?, ?)',
      [user.name, user.email]
    );
    console.log('ID d’insertion :', result.insertId);
    return result;
  } catch (err) {
    console.error('Erreur d’insertion :', err);
    throw err;
  }
}

Mise à jour des données (UPDATE)

Exemple

async function updateUser(id, updates) {
  try {
    const [result] = await promisePool.query(
      'UPDATE users SET name = ?, email = ? WHERE id = ?',
      [updates.name, updates.email, id]
    );
    console.log('Lignes affectées:', result.affectedRows);
    return result;
  } catch (err) {
    console.error('Erreur de mise à jour:', err);
    throw err;
  }
}

Suppression de données (DELETE)

Exemple

async function deleteUser(id) {
  try {
    const [result] = await promisePool.query(
      'DELETE FROM users WHERE id = ?',
      [id]
    );
    console.log('Lignes supprimées:', result.affectedRows);
    return result;
  } catch (err) {
    console.error('Erreur de suppression:', err);
    throw err;
  }
}

Fonctionnalités avancées et bonnes pratiques

Gestion des transactions

Exemple

async function transferFunds(fromId, toId, amount) {
  let connection;
  try {
    // Obtenir une connexion depuis le pool
    connection = await promisePool.getConnection();
   
    // Démarrer une transaction
    await connection.beginTransaction();
   
    // Effectuer l'opération de transfert
    await connection.query(
      'UPDATE accounts SET balance = balance - ? WHERE id = ?',
      [amount, fromId]
    );
   
    await connection.query(
      'UPDATE accounts SET balance = balance + ? WHERE id = ?',
      [amount, toId]
    );
   
    // Valider la transaction
    await connection.commit();
    console.log('Transfert réussi');
  } catch (err) {
    // Annuler en cas d'erreur
    if (connection) await connection.rollback();
    console.error('Échec du transfert :', err);
    throw err;
  } finally {
    // Rendre la connexion au pool
    if (connection) connection.release();
  }
}

Requêtes préparées

Les requêtes préparées peuvent améliorer les performances et prévenir l'injection SQL :

Exemple

async function getUserById(id) {
  try {
    // Préparer une requête préparée
    const [rows] = await promisePool.execute(
      'SELECT * FROM users WHERE id = ?',
      [id]
    );
    return rows[0];
  } catch (err) {
    console.error('Erreur de requête :', err);
    throw err;
  }
}

Écoute des événements du pool de connexions

Exemple

pool.on('connection', (connection) => {
  console.log('Nouvelle connexion établie');
});

pool.on('acquire', (connection) => {
  console.log('Connexion acquise');
});

pool.on('release', (connection) => {
  console.log('Connexion libérée');
});

pool.on('enqueue', () => {
  console.log('En attente d'une connexion disponible');
});

Gestion des erreurs et débogage

Types d'erreurs courantes

  1. Erreurs de connexion: serveur de base de données inaccessible, échec d'authentification, etc.
  2. Erreurs de syntaxe de requête: instructions SQL incorrectes
  3. Violations de contraintes: telles que des clés primaires en double, des contraintes de clé étrangère, etc.
  4. Erreurs de délai d'attente: le temps d'exécution de la requête est trop long

Stratégies de gestion des erreurs

Exemple

async function safeQuery(sql, params) {
  try {
    const [rows] = await promisePool.query(sql, params);
    return rows;
  } catch (err) {
    // Prendre différentes mesures en fonction du type d'erreur
    switch (err.code) {
      case 'ER_DUP_ENTRY':
        console.warn('Entrée en double :', err.sqlMessage);
        throw new Error('Les données existent déjà');
      case 'ECONNREFUSED':
        console.error('Impossible de se connecter à la base de données');
        throw new Error('Service indisponible, veuillez réessayer plus tard');
      default:
        console.error('Erreur de base de données :', err);
        throw err;
    }
  }
}

Conseils d'optimisation des performances

  1. Définissez correctement la taille du pool de connexions: généralement 2-3 fois le nombre de cœurs de CPU
  2. Utilisez un pool de connexions au lieu d'une connexion unique: en particulier dans les applications web
  3. Utilisez les index de manière appropriée: accélérez les performances des requêtes
  4. Opérations par lots: réduisez les allers-retours
  5. Utilisez des requêtes préparées: améliorez les performances des requêtes répétées
  6. Libérez régulièrement les ressources: évitez les fuites de connexion

Exemple d'insertion par lots :

Exemple

async function batchInsertUsers(users) {
  const values = users.map(user => [user.name, user.email]);
 
  try {
    const [result] = await promisePool.query(
      'INSERT INTO users (name, email) VALUES ?',
      [values]
    );
    console.log('Lignes insérées :', result.affectedRows);
    return result;
  } catch (err) {
    console.error('Erreur d'insertion par lots :', err);
    throw err;
  }
}

Considérations de sécurité

  1. Ne concaténez jamais les chaînes SQL: utilisez des requêtes paramétrées pour éviter les injections SQL
  2. Limitez les permissions des utilisateurs de la base de données: les comptes d'application n'ont besoin que des permissions nécessaires
  3. Chiffrez les données sensibles: par exemple, les mots de passe doivent être stockés avec des hachages salés
  4. Utilisez des connexions SSL: les connexions chiffrées sont recommandées en production
  5. Mettez régulièrement à jour les dépendances: maintenez le paquet mysql2 à jour

Structure complète du projet d'exemple

project/
├── config/
│   └── db.js          # 数据库配置
├── models/
│   └── userModel.js   # 数据模型
├── services/
│   └── userService.js # 业务逻辑
├── app.js             # 主应用文件
└── package.json

exemple de db.js :

Exemple

const mysql = require('mysql2');

const pool = mysql.createPool({
  host: process.env.DB_HOST || 'localhost',
  user: process.env.DB_USER || 'root',
  password: process.env.DB_PASSWORD || '',
  database: process.env.DB_NAME || 'test_db',
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0
});

module.exports = pool.promise();
Autres extensions