Jak zdobyć rdzeń, aby wykorzystać konfigurację MySQL master / slave?

21

Przeczytałem to pytanie replikacja master / slave MySQL nie działa i jego odpowiedź:

Korzystanie z baz danych slave jest ledwo zaimplementowane w rdzeniu Drupala. Jeśli opracowujesz własne moduły, wówczas wywołania db_query muszą określić, że chcą używać bazy danych slave za pomocą tablicy $ options. Zobacz DatabaseConnection :: defaultOptions, aby dowiedzieć się, jak ustawić tę tablicę.

Czy istnieje sposób bez zabijania kociąt hakujących rdzeń, aby uzyskać db_query()i db_select()wykonać więcej niewolniczych zapytań SELECT?

Domyślnie funkcje te będą odpytywały master, chyba że otrzymają specjalne polecenie, aby zapytać slave (zobacz ich API). Musisz napisać db_query($query, $args, array('target' => 'slave')), aby wysłać zapytanie do urządzenia podrzędnego, a rdzeń (i wszystkie moduły) nie są napisane, aby to osiągnąć.

Wydaje się, że wykorzystują to tylko wyszukiwanie (patrz część podrzędna) i agregator.

Edycja: 25 października.
Widziałem, że nie ma już przepływu 7, ale nie jestem pewien, czy to teraz bardzo pomaga.
Nie znalazłem czegoś istotnego, więc spróbujmy dostać małą nagrodę, aby pomóc w uzyskaniu odpowiedzi.

Edycja: 31 października 31.
Martwię się głównie o komentarze Crella dotyczące tego tematu: Co zrobić z niewolnikami? .
Głównie występują problemy, gdy wysyłam SELECTzapytania do urządzenia podrzędnego, co dzieje się z opóźnieniami w replikacji i faktem, że mogę chcieć zrobić to node_load()zaraz po zapisaniu nowego węzła.

tostinni
źródło

Odpowiedzi:

17

Oto jak obecnie to wdrażam.

Najpierw musisz skonfigurować klasę SelectQueryExtender w następujący sposób:

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

Gdy to zrobisz, wystarczy, że uzyskasz wszystkie inne zapytania, aby rozszerzyć wzmacniacz sygnału. :) Jeśli to ma sens. Oto fragment kodu.

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

A teraz wszystkie twoje SelectQuery trafiły w niewolnika ;-) To jedyny sposób, w jaki udało mi się to osiągnąć. W każdym razie działa świetnie.

Również jeśli masz to w module niestandardowym, możesz ustawić SlaveTarget tak, aby był w pliku SlaveTarget.inc i dodać pliki [] = SlaveTarget.inc do pliku informacji o module.

ericduran
źródło
Cześć Eric, dziękuję za odpowiedź, co martwi mnie głównie ten wątek: Co zrobić z niewolnikami? i komentarz Crella dotyczący niewolnika . Czy twoje rozwiązanie jest w każdym razie bezpieczne? Czy ograniczasz niektóre SELECTzapytania? Jak radzisz sobie z opóźnieniami w replikacji i faktem, że ładowanie węzła zaraz po zapisaniu może powodować problemy?
tostinni
Spowoduje to zmianę bazy danych na slave tylko w przypadku zapytań Select. Dzieje się tak tylko wtedy, gdy zapytanie zostało napisane przy użyciu SelectQuery, a nie db_query, więc nie trzeba się martwić o wstawienie lub aktualizację ukierunkowaną na slave. Obsługujemy to w 3 dużych środowiskach produkcyjnych bez żadnych problemów. Nie martwiłem się zbytnio replikacją mysql jako niemal natychmiastową (w moim przypadku), ale widzę, jak może to być mały problem w niektórych środowiskach.
ericduran
Dzięki za odpowiedzi, to świetne rozwiązanie, zobaczę, czy jest to opłacalne w naszym środowisku.
tostinni
Eric, czy ten kod jest gdzieś jako moduł contrib lub sandbox?
paul-m
@ paul-m: patrz drupal.org/project/autoslave .
smokris
5

W AutoSlave przekierowuje Moduł SELECTzapytań tylko do odczytu Replicant baz danych, a to uwzględnia replikacji lag.

Zgodnie z dokumentacją modułu używa replikatora tylko do odczytu, gdy spełnione są wszystkie następujące warunki:

  1. Zapytanie jest zapytaniem wybranym
  2. Tabele w wybranym zapytaniu nie zostały zapisane podczas żądania i w założonym opóźnieniu replikacji
  3. Transakcja nie została rozpoczęta
  4. Tabele w wybranym zapytaniu nie są określone w opcji „tabele” w ustawieniach sterownika
  5. Blokada nie została uruchomiona (obsługiwana podstawowa blokada bazy danych i blokada pamięci)
smokris
źródło
1

z tego, co usłyszałem podczas ostatniego Drupal BADcamp Pressflow jest właściwą drogą, jeśli chcesz konfiguracji master / slave. Będziesz ograniczony do MySQL jako DB. Sprawdź także „ grupę wysokiej wydajności ” na do

uwe
źródło
1
Obecnie Pressflow 7 = D7, nie ma (jeszcze) tego, że Pressflow robi to D7 nie :(
tostinni 27.10.11
1

Pomimo wszystkich niesamowitych prac wykonanych na warstwie abstrakcji bazy danych w Drupal 7, nadal jest to zaskakująco trudne do zrobienia z rdzeniem Drupal po wyjęciu z pudełka. Jak wspomnieli inni, AutoSlave jest opcją, chociaż nie próbowałem tego z powodu mojej upartej odmowy uwierzenia, że ​​powinno to być tak trudne.

Znalazłem prostsze rozwiązanie: Aby skierować wszystkie SELECT s do serwera podrzędnego, należy utworzyć plik zatytułowany select.incw includes/database/mysqlkatalogu głównym z następującą zawartością:

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

Ta metoda wiąże się z pewnym ryzykiem:

  1. Ta metoda przejmie wszystkie SELECT s i skieruje je do niewolnika, co niewątpliwie spowoduje problemy, jeśli wystąpi opóźnienie w replikacji. Przeczytaj to zdanie jeszcze raz.
  2. Po uaktualnieniu rdzenia Drupal plik może zostać usunięty.
  3. Jeśli rdzeń Drupala zacznie kiedykolwiek dostarczać własny includes/database/mysql/select.inc, plik zostanie nadpisany podczas aktualizacji i będziesz musiał zacząć utrzymywać własną poprawioną wersję pliku select.inc dostarczanego z rdzeniem Drupal.

Jeśli nie masz żadnych serwerów podrzędnych określonych w pliku settings.php, powyższy kod nie spowoduje problemu. Nadal z wdziękiem obniży się do korzystania z serwera głównego .

q0rban
źródło
Tak, pojawia się, mimo że połączenie można ustawić na „slave”, jeśli samo zapytanie nie ma target => 'slave'ustawionej opcji, nadal będzie działać na połączeniu domyślnym. Boli, nie jest łatwiej ustawić cel połączenia na query_alterpoziomie.
David Thomas