Um das zu erreichen, was Sie tun möchten, können Sie die FEDERATED
Speicher-Engine auf beiden Servern in Verbindung mit Triggern verwenden, damit jeder Server die Datenbank des anderen Servers aktualisieren kann.
Dies ist nicht gerade eine einfache Standardlösung, da hierfür zusätzliche Vorsichtsmaßnahmen erforderlich sind und Sie entscheiden müssen, ob Konsistenz oder Isolationstoleranz wichtiger sind, und die Abfragen fehlschlagen können, wenn der andere Server nicht verfügbar ist (mehr Konsistenz) ) oder verwenden Sie a CONTINUE HANDLER
, um Fehler zu unterdrücken (Isolationstoleranz).
Aber hier ist ein extrem vereinfachtes Beispiel.
Jeder Server hätte die gleiche Konfiguration.
Die lokale Benutzertabelle:
CREATE TABLE user (
username varchar(64) NOT NULL,
password varbinary(48) NOT NULL, /* encrypted of course */
PRIMARY KEY(username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Eine lokale Tabelle, die mit der Benutzertabelle auf dem anderen Server verbunden ist.
CREATE TABLE remote_user (
username varchar(64) NOT NULL,
password varbinary(48) NOT NULL, /* encrypted of course */
PRIMARY KEY(username)
) ENGINE=FEDERATED DEFAULT CHARSET=utf8 CONNECTION='mysql://username:pass@the_other_host:port/schema/user';
Durch Auswahl von remote_user auf einem Server werden die Datensätze vom anderen Server abgerufen, und durch Einfügen / Aktualisieren / Löschen in dieser Tabelle werden die Daten auf dem anderen Server geändert.
Wir erstellen also Trigger, die den Zweck der Aktualisierung des Entfernungsservers erfüllen. Sie werden als BEFORE
Auslöser geschrieben, mit der Idee, dass wir uns selbst nichts antun wollen, was wir dem anderen Server nicht antun können - zum Beispiel, wenn auf dem anderen Server bereits ein Benutzername vorhanden ist, aber nicht hier. Wir möchten, dass die Einfügung auf dem anderen Server einen Fehler auslöst, der uns daran hindert, den Benutzer hier zu erstellen ... im Gegensatz zum Erstellen eines Benutzers hier mit einem widersprüchlichen Benutzernamen. Dies ist natürlich eine der Kompromissentscheidungen, die Sie treffen müssen.
DELIMITER $$
CREATE TRIGGER user_bi BEFORE INSERT ON user FOR EACH ROW
BEGIN
INSERT INTO remote_user (username,password) VALUES (NEW.username,NEW.password);
END $$
CREATE TRIGGER user_bu BEFORE UPDATE ON user FOR EACH ROW
BEGIN
UPDATE remote_user
SET username = NEW.username,
password = NEW.password
WHERE username = OLD.username;
END $$
CREATE TRIGGER user_bd BEFORE DELETE ON user FOR EACH ROW
BEGIN
DELETE FROM remote_user
WHERE username = OLD.username;
END $$
DELIMITER ;
Dies ist keine perfekte Lösung und keine Hochverfügbarkeitslösung, da sie auf einer soliden Konnektivität zwischen den beiden Systemen beruht. Selbst wenn Sie InnoDB und Transaktionen verwenden, sind die Aktionen, die Sie für die Zieltabelle ausführen, nicht Teil Ihrer lokalen Transaktion und kann nicht zurückgesetzt werden.
Ich benutze den FEDERATED
Motor ziemlich oft; Es ist praktisch für eine Reihe kreativer Zwecke in meiner Umgebung, einschließlich einer Situation, in der ich eine von einem Auslöser gestartete Verbundabfrage verwendet habe, um einer fremden Datenquelle Fremdschlüsseleinschränkungen aufzuerlegen. Ich beschränke die Verwendung jedoch auf Back-End-Prozesse, bei denen unerwartete Probleme wie Zeitüberschreitungen, Codierungsfehler oder Server-zu-Server-Netzwerk- / Ausfall- / Isolationsereignisse nicht dazu führen können, dass der Endbenutzer auf einer unserer Websites Probleme hat . Ihre Fähigkeit, eine solche Situation zu tolerieren, wäre ein entscheidender Faktor dafür, ob dies eine geeignete Lösung ist.
Eine Alternative wäre, Ihre beiden Server in der Master / Master-Replikation zu konfigurieren. Dazu müssten Sie auf jedem Server unterschiedliche Datenbanknamen verwenden, damit bei den meisten replizierenden Ereignissen die beiden Server möglicherweise nicht miteinander in Konflikt geraten können. Im schlimmsten Fall, wenn Sie die Konnektivität verlieren oder auf einen Replikationsfehler stoßen, werden die beiden Standorte weiterhin unabhängig voneinander ausgeführt und Sie können erneut synchronisieren und wiederherstellen. Die Konfiguration würde ungefähr so aussehen:
database_a database for site A
database_b database for site B
database_c database for only the shared table(s)
Dann in database_a und database_b:
CREATE ALGORITHM=MERGE SQL SECURITY INVOKER VIEW user AS SELECT * FROM c.user;
MySQL behandelt database_a.user und database_b.user als Aliase für die "echte" Benutzertabelle database_c.user, sodass Sie Ihre Anwendung nur ändern müssen, wenn Sie die angegebene Datenbank verwenden (dh nicht konfigurieren müssen) um zu verstehen, dass sich die Benutzertabelle tatsächlich in einem anderen Schema befand, da die Ansicht mit dieser Konfiguration ziemlich transparent funktioniert). Wenn die Schemas Fremdschlüssel für die Benutzertabelle haben, würden Sie diese für die wahre Basistabelle database_c.user deklarieren.
Konfigurieren Sie die beiden Server zu replizieren alles, aber Satz auto_increment_increment
und in auto_increment_offset
geeigneter Weise, so dass Sie nicht haben widerstreit Autoinkrement-Werte auf der gemeinsamen Tabelle (n), wenn Ihre Tabellen Autoinkrement verwenden. (Beachten Sie, dass in der Dokumentation angegeben ist, dass diese Variablen nur für NDB
Tabellen gelten, dies jedoch nicht korrekt ist.)
Ein zusätzlicher Vorteil dieses Setups besteht darin, dass Ihre beiden Server dann über ein vollständiges Duplikat der Daten der anderen Site verfügen, die Sie möglicherweise zu Ihrem Vorteil für die Wiederherstellung nach einem Hardwarefehler auf einem der Server verwenden könnten.