it-swarm.it

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

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

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

C'è un modo senza uccidere i gattini l'hacking del core per ottenere db_query() e db_select() per fare più query SELECT su slave?

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 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 un po 'di grazia per aiutarlo a ottenere una risposta.

Modifica: 31 ottobre
Sono principalmente preoccupato per commenti di Crell riguardo a questo argomento: Cosa fare con gli schiavi? .
Principalmente, ci sono problemi se invio SELECT query allo slave, cosa succede con i ritardi nella replica e il fatto che potrei voler fare una node_load() subito dopo salvataggio di un nuovo nodo.

20
tostinni

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.

17
ericduran

Il modulo AutoSlave reindirizza SELECT query a database replicanti di sola lettura, e prende in considerazione il 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)
5
smokris

da quello che ho sentito nel recente Drupal BADcamp Pressflow è la strada da percorrere se vuoi configurazioni master/slave. Sarai limitato a Mysql come DB. Inoltre, controlla "- gruppo ad alte prestazioni "on do.

1
uwe

Nonostante tutto lo straordinario lavoro svolto sul livello di astrazione del database in Drupal 7, questo è ancora sorprendentemente difficile da fare con Drupal core pronto all'uso. altri hanno menzionato, 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 SELECTs sul server slave, si crea un file intitolato select.inc all'interno del core includes/database/mysql directory 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 SELECTs e li indirizzerà allo slave, il che causerà senza dubbio problemi in caso di ritardo nella replica. Leggi di nuovo quella frase.
  2. Quando si aggiorna Drupal core, è possibile che questo file venga eliminato.
  3. Se Drupal dovesse mai iniziare a spedire con il proprio 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 nell'uso del server master .

1
q0rban