Come ottenere core per sfruttare una configurazione master / slave MySQL?


21

Ho letto questa domanda La replica master / slave di MySQL non funziona e la sua risposta:

L'uso dei database slave è a malapena implementato nel core di Drupal. Se stai sviluppando i tuoi moduli, le chiamate a db_query devono specificare che vogliono usare il database slave usando l'array $ options. Vedere DatabaseConnection :: defaultOptions per come impostare questo array.

Esiste un modo senza uccidere i gattini che hackerano il core per ottenere db_query()e db_select()fare più query SELECT sugli schiavi?

Per impostazione predefinita, queste funzioni interrogano il master a meno che non sia espressamente richiesto di interrogare lo slave (vedere la loro API). Devi scrivere db_query($query, $args, array('target' => 'slave'))per interrogare lo slave e il core (e tutti i moduli) non sono scritti per raggiungere questo obiettivo.

Solo la ricerca (vedi la parte slave) e l'aggregatore sembrano sfruttare questo.

Modifica: 25 ottobre.
Ho visto pressflow 7 uscito ma non sono sicuro che sia di grande aiuto in questo momento.
Non ho trovato qualcosa di rilevante, quindi proviamo una piccola ricompensa per aiutare a ottenere una risposta.

Modifica: 31 ott.
Sono principalmente preoccupato per i commenti di Crell su questo argomento: cosa fare degli schiavi? .
Principalmente, ci sono problemi se invio SELECTquery allo slave, cosa succede con i ritardi nella replica e il fatto che potrei voler fare node_load()subito dopo aver salvato un nuovo nodo.

Risposte:


17

Ecco come lo implemento attualmente.

Per prima cosa devi impostare una classe SelectQueryExtender in questo modo:

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

Una volta che lo hai fatto, tutto ciò che devi fare è ottenere tutte le altre query per estendere l'extender. :) se questo ha senso. Ecco lo snippet.

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

E ora tutto il tuo SelectQuery ha colpito lo schiavo ;-) Questo è l'unico modo in cui sono stato in grado di farlo. Comunque funziona benissimo.

Inoltre, se disponi di questo su un modulo personalizzato, puoi impostare SlaveTarget in modo che si trovi sul file SlaveTarget.inc e aggiungere un file [] = SlaveTarget.inc al file di informazioni del modulo.


Ciao Eric, grazie per la tua risposta, ciò che mi preoccupa principalmente è questa discussione: cosa fare degli schiavi? e il commento di Crell riguardo allo schiavo . Quindi la tua soluzione è sicura in ogni caso? Limiti alcune SELECTquery? Come gestite i ritardi nella replica e il fatto che il caricamento di un nodo subito dopo il salvataggio possa causare problemi?
tostinni,

Questo sta cambiando il database in slave solo su query Select. Ciò accade solo quando la query è stata scritta con SelectQuery non db_query, quindi non è necessario preoccuparsi e inserire o aggiornare la destinazione allo slave. Lo stiamo eseguendo su 3 enormi ambienti di produzione senza problemi. Non mi sono preoccupato molto della replica di mysql come quasi istantanea (nel mio caso), ma posso vedere come potrebbe essere un piccolo problema in alcuni ambienti.
ericduran,

Grazie per le risposte, è un'ottima soluzione, vedrò se questo è praticabile nel nostro ambiente.
tostinni,

Eric, questo codice esiste da qualche parte come modulo contrib o sandbox?
paul-m,


5

Il modulo AutoSlave reindirizza le SELECTquery ai database replicanti di sola lettura e tiene conto del ritardo di replica.

Secondo i documenti del modulo, utilizza il replicante di sola lettura quando sono vere tutte le seguenti condizioni:

  1. La query è una query selezionata
  2. Le tabelle nella query selezionata non sono state scritte durante la richiesta e all'interno del ritardo di replica ipotizzato
  3. Una transazione non è stata avviata
  4. Le tabelle nella query di selezione non sono specificate nell'opzione "tabelle" nelle impostazioni del driver
  5. Un blocco non è stato avviato (core db-lock e memcache-lock supportati)

1

da quello che ho sentito al recente Drupal BADcamp Pressflow è la strada da percorrere se vuoi configurazioni master / slave. Sarai limitato a Mysql come DB. Inoltre, checkout il " gruppo ad alte prestazioni " su Do


1
Attualmente Pressflow 7 = D7, non c'è nulla (ancora) che Pressflow faccia che D7 non fa :(
tostinni,

1

Nonostante tutto il fantastico lavoro svolto sul livello di astrazione del database in Drupal 7, questo è ancora sorprendentemente difficile da fare con il core Drupal pronto all'uso. Come altri hanno già detto, AutoSlave è un'opzione, anche se non uno che ho tentato a causa del mio testardo rifiuto di credere che dovrebbe essere così difficile farlo.

Una soluzione più semplice che ho trovato è la seguente. Per instradare tutti SELECT i messaggi di posta elettronica sul server slave, creare un file intitolato select.incall'interno della includes/database/mysqldirectory principale con i seguenti contenuti:

<?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".
 */

Ci sono alcuni rischi con questo metodo:

  1. Questo metodo dirotterà tutti SELECT i messaggi e li indirizzerà allo slave, il che causerà senza dubbio problemi in caso di ritardo nella replica. Leggi di nuovo quella frase.
  2. Quando aggiorni Drupal core, è possibile che questo file venga eliminato.
  3. Se Drupal core dovesse iniziare a essere spedito da solo includes/database/mysql/select.inc, il tuo file verrebbe sovrascritto durante l'aggiornamento e dovresti iniziare a mantenere la tua versione patchata di select.inc fornita con Drupal core.

Se non hai alcun server slave specificato in settings.php, il codice sopra riportato non causerà un problema. Si degraderà comunque con garbo all'utilizzo del server principale .


Sì, appare anche se la connessione può essere impostata su "slave", se la query stessa non ha l' target => 'slave'opzione impostata, verrà comunque eseguita sulla connessione predefinita. È un dolore non è più facile impostare l'obiettivo di connessione più facilmente a query_alterlivello.
David Thomas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.