web-dev-qa-db-fra.com

Comment obtenir du noyau pour tirer parti d'une configuration maître / esclave MySQL?

J'ai lu cette question la réplication maître/esclave MySQL ne fonctionne pas et sa réponse:

L'utilisation de bases de données esclaves est à peine implémentée dans Drupal core. Si vous développez vos propres modules, les appels à db_query doivent spécifier qu'ils souhaitent utiliser la base de données esclave à l'aide du tableau $ options. Voir DatabaseConnection: : defaultOptions pour savoir comment définir ce tableau.

Y a-t-il un moyen sans tuer des chatons pirater le noyau pour obtenir db_query() et db_select() pour faire plus de requêtes SELECT esclaves?

Par défaut, ces fonctions interrogeront le maître, sauf indication contraire d'interroger l'esclave (voir leur API). Vous devez écrire db_query($query, $args, array('target' => 'slave')) afin d'interroger l'esclave et le noyau (et tous les modules) ne sont pas écrits pour y parvenir.

Seulement recherche (voir la partie esclave) et l'agrégateur semble en tirer parti.

Modifier: 25 octobre
J'ai vu que pressflow 7 est sorti mais je ne sais pas si cela aide beaucoup en ce moment.
Je n'ai pas trouvé quelque chose de pertinent, alors essayons un peu de générosité pour aider à obtenir une réponse.

Modifier: 31 octobre
Je m'inquiète principalement Commentaires de Crell concernant ce sujet: Que faire des esclaves? .
Principalement, y a-t-il des problèmes si j'envoie des requêtes SELECT à l'esclave, ce qui se passe avec les retards dans la réplication et le fait que je peux vouloir faire une node_load() juste après enregistrer un nouveau nœud.

20
tostinni

Voici comment j'implémente actuellement ceci.

Vous devez d'abord configurer une classe SelectQueryExtender comme ceci:

class SlaveTarget extends SelectQueryExtender {
  public function __construct(SelectQueryInterface $query, DatabaseConnection $connection) {
    if ($connection->getTarget() != 'slave') {
      $connection = Database::getConnection('slave', $connection->getKey());
    }
    parent::__construct($query, $connection);
    $this->addTag('SlaveTarget');
  }
}

Une fois que vous avez cela, alors tout ce que vous avez à faire est d'obtenir toutes les autres requêtes pour étendre l'extension. :) si ça a du sens. Voici l'extrait.

/**
 * Implements hook_query_alter().
 */
function example_query_alter(QueryAlterableInterface $query) { 
  if (is_a($query, 'SelectQuery') && !$query->hasTag('SlaveTarget')) {
    $query->extend('SlaveTarget');
  }
}

Et maintenant, tous vos SelectQuery ont atteint l'esclave ;-) C'est la seule façon dont j'ai pu accomplir cela. Quoi qu'il en soit, cela fonctionne très bien.

De plus, si vous l'avez sur un module personnalisé, vous pouvez configurer le SlaveTarget pour qu'il soit dans le fichier SlaveTarget.inc et ajouter un fichier [] = SlaveTarget.inc à votre fichier d'informations sur le module.

17
ericduran

Le module AutoSlave redirige les requêtes SELECT vers des bases de données réplicantes en lecture seule, et il prend en compte le retard de réplication.

Selon les documents du module, il utilise uniquement le réplicateur en lecture seule lorsque toutes les conditions suivantes sont remplies:

  1. La requête est une requête de sélection
  2. Les tables de la requête de sélection n'ont pas été écrites pendant la demande et dans le délai de réplication supposé
  3. Une transaction n'a pas été démarrée
  4. Les tables de la requête de sélection ne sont pas spécifiées dans l'option "tables" des paramètres du pilote
  5. Un verrou n'a pas été démarré (core db-lock et memcache-lock pris en charge)
5
smokris

d'après ce que j'ai entendu lors de la récente Drupal BADcamp Pressflow est la voie à suivre si vous voulez des configurations maître/esclave. Vous serez limité à Mysql en tant que DB. En outre, consultez le "- groupe haute performance "on do.

1
uwe

Malgré tout le travail incroyable accompli sur la couche d'abstraction de la base de données dans Drupal 7, cela est toujours étonnamment difficile à faire avec Drupal core hors de la boîte. Comme d'autres ont mentionné, AutoSlave est une option, bien que je n'en ai pas essayé en raison de mon refus obstiné de croire que cela devrait être si difficile à faire.

Une solution plus simple que j'ai trouvée est la suivante. Pour router tous SELECTs vers le serveur esclave, vous créez un fichier intitulé select.inc à l'intérieur du noyau includes/database/mysql répertoire avec le contenu suivant:

<?php

/**
 * @file
 * Select builder for MySQL database engine, routing all SELECTs to the slave.
 */

/**
 * @addtogroup database
 * @{
 */

class SelectQuery_mysql extends SelectQuery {
  public function __construct($table, $alias = NULL, DatabaseConnection $connection, $options = array()) {
    $key = $connection->getKey();
    $connection = Database::getConnection('slave', $key);
    $options['target'] = 'slave';
    parent::__construct($table, $alias, $connection, $options);
  }
}

/**
 * @} End of "addtogroup database".
 */

Il y a des risques avec cette méthode:

  1. Cette méthode détournera tous SELECTs et les dirigera vers l'esclave, ce qui causera sans aucun doute des problèmes si vous avez un retard dans la réplication. Relisez cette phrase.
  2. Lorsque vous mettez à niveau Drupal core, il est possible que ce fichier soit supprimé.
  3. Si Drupal core devait commencer à être expédié avec son propre includes/database/mysql/select.inc, votre fichier serait écrasé lors de la mise à niveau, et vous devrez commencer à maintenir votre propre version corrigée du select.inc fourni avec Drupal core.

Si vous n'avez aucun serveur esclave spécifié dans settings.php, le code ci-dessus ne posera pas de problème. Il se dégradera toujours avec élégance en utilisant le serveur maître .

1
q0rban