Heim > Datenbank > MySQL-Tutorial > Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL

Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL

青灯夜游
Freigeben: 2021-09-06 17:54:42
Original
2709 Leute haben es durchsucht

Dieser Artikel führt Sie durch die Master-Slave-, Master-Slave- und Lese-Schreib-Trennung in MySQL. Ich hoffe, er wird Ihnen hilfreich sein!

1. Die Grundprinzipien von MySQL-Master und -Backup

Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
Im Zustand 1 greift der Client zum Lesen und Schreiben direkt auf Knoten A zu, und Knoten B ist die Backup-Datenbank von A. Er synchronisiert lediglich die Aktualisierungen von A bis Lokal ausgeführt. Dadurch bleiben die Daten der Knoten B und A gleich. Wenn eine Umschaltung erforderlich ist, wechselt es in den Zustand 2. Zu diesem Zeitpunkt liest und schreibt der Client auf Knoten B, und Knoten A ist die Standby-Datenbank von B. [Verwandte Empfehlungen: MySQL-Video-Tutorial]

Obwohl im Status 1 nicht direkt auf Knoten B zugegriffen wird, wird empfohlen, den Standby-Knoten B in den schreibgeschützten Modus zu versetzen. Dafür gibt es mehrere Gründe:

1. Manchmal werden einige operative Abfrageanweisungen zur Überprüfung in die Standby-Datenbank gestellt, um Fehlbedienungen zu verhindern.

3 Verwenden Sie den schreibgeschützten Status, um die Rolle des Knotens zu bestimmen

Wenn die Standby-Datenbank auf schreibgeschützt eingestellt ist, wie kann sie synchron mit der Hauptdatenbank aktualisiert werden?

Die Einstellung „Schreibgeschützt“ ist für Benutzer mit Superprivilegien ungültig und der Thread, der für synchronisierte Updates verwendet wird, verfügt über Superprivilegien

Die folgende Abbildung ist ein vollständiges Flussdiagramm einer Update-Anweisung, die auf Knoten A ausgeführt und dann mit Knoten B synchronisiert wird:


Zwischen der Standby-Datenbank B und der Primärdatenbank A wird eine lange Verbindung aufrechterhalten. In der Hauptbibliothek A gibt es einen Thread, der für die lange Verbindung der Standby-Bibliothek B zuständig ist. Der vollständige Prozess der Transaktionsprotokollsynchronisierung ist wie folgt: Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
1. Verwenden Sie den Befehl „Change Master“ für die Standby-Datenbank B, um die IP, den Port, den Benutzernamen und das Kennwort der Primärdatenbank A und den Speicherort festzulegen, von dem aus das Binlog angefordert werden soll Der Speicherort enthält den Dateinamen und den Protokolloffset

2. Führen Sie den Befehl „Start Slave“ in der Standby-Datenbank B aus. Zu diesem Zeitpunkt startet die Standby-Datenbank zwei Threads, nämlich io_thread und sql_thread im Bild. Unter anderem ist io_thread für den Verbindungsaufbau mit der Hauptbibliothek verantwortlich

3 Nachdem die Hauptbibliothek A den Benutzernamen und das Kennwort überprüft hat, beginnt sie, das Binlog entsprechend dem von der Standby-Bibliothek B übergebenen Speicherort zu lesen und zu senden es nach B

4. Standby-Bibliothek B Nachdem Sie das Binlog erhalten haben, schreiben Sie es in eine lokale Datei, das Transitprotokoll genannt

5.sql_thread liest das Transitprotokoll, analysiert die Befehle im Protokoll und führt es aus

Aufgrund von Mit der Einführung des Multithread-Replikationsschemas entwickelte sich sql_thread zu mehreren Threads. Auf diese Weise muss die Aktiv-Standby-Beziehung während des Wechsels nicht geändert werden. Es gibt ein Problem, das in der Doppel-M-Struktur gelöst werden muss. Die Geschäftslogik aktualisiert eine Anweisung an Knoten A und sendet dann das generierte Binlog Knoten B. Nachdem Knoten B dieses Binlog ausgeführt hat, wird es auch nach Update-Anweisungen generiert. Wenn Knoten A dann auch die Standby-Datenbank von Knoten B ist, entspricht dies der einmaligen Ausführung des neu generierten Binlogs von Knoten B. Anschließend wird die Aktualisierungsanweisung kontinuierlich in einer Schleife zwischen den Knoten A und B ausgeführt ist die Schleifenreplikation

MySQL zeichnet die Server-ID der Instanz auf, in der dieser Befehl zum ersten Mal im Binlog ausgeführt wurde. Daher kann die folgende Logik verwendet werden, um das Problem der zirkulären Replikation zwischen zwei Knoten zu lösen:

1 Es wird festgelegt, dass die Server-IDs der beiden Bibliotheken unterschiedlich sein müssen. Wenn sie gleich sind, können sie nicht als Master festgelegt werden -Backup-Beziehung 2 .Eine Standby-Datenbank empfängt das Binlog und generiert während des Wiedergabevorgangs ein neues Binlog mit derselben Server-ID wie das ursprüngliche Binlog

3 Nachdem jede Datenbank das von ihrer Hauptdatenbank gesendete Protokoll empfangen hat, wird es zuerst bestimmt Wenn die Server-ID mit Ihrer eigenen übereinstimmt, bedeutet dies, dass das Protokoll von Ihnen selbst erstellt wurde. Verwerfen Sie das Protokoll also einfach direkt. Der Ausführungsablauf des Doppel-M-Strukturprotokolls ist wie folgt:

1 Die Transaktionen wurden aktualisiert von Knoten A werden in der Server-ID von Binlog A aufgezeichnetErfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
2 Nachdem es einmal zur Ausführung an Knoten B gesendet wurde, ist die Server-ID des von Knoten B generierten Binlogs auch die Server-ID von A

3 Knoten A und A stellt fest, dass die Server-ID mit seiner eigenen übereinstimmt. Dieses Protokoll wird nicht erneut verarbeitet. Daher wird hier die Endlosschleife unterbrochen

3. Primäre und sekundäre Verzögerungen

1. Was sind primäre und sekundäre Verzögerungen?

Die mit der Datensynchronisierung verbundenen Zeitpunkte umfassen hauptsächlich die folgenden drei:

1 Die Hauptdatenbank A schließt eine Transaktion ab und schreibt sie in das Binlog. Dieser Moment wird als T1 aufgezeichnet Standby-Datenbank B und die Standby-Datenbank Der Moment, in dem B den Empfang dieses Binlogs beendet, wird als T2

3 aufgezeichnet. Nachdem die Standby-Datenbank B diese Transaktion ausgeführt hat, wird der Moment als T3

Die sogenannte Master-Standby-Verzögerung wird aufgezeichnet dass dieselbe Transaktion zwischen dem Zeitpunkt, zu dem die Standby-Datenbank ausgeführt wird, und dem Zeitpunkt der Master-Datenbank abgeschlossen ist. Der Unterschied zwischen der Ausführungsabschlusszeit, d Das Rückgabeergebnis zeigt seconds_behind_master an, mit dem angegeben wird, um wie viele Sekunden die aktuelle Standby-Datenbank verzögert ist

seconds_behind_master Die Berechnungsmethode lautet wie folgt:

1. Im Binlog jeder Transaktion gibt es ein Zeitfeld, das zum Aufzeichnen der in die Hauptdatenbank geschriebenen Zeit verwendet wird.

2 Die Standby-Datenbank entnimmt den Wert des Zeitfelds der aktuell ausgeführten Transaktion Differenz zur aktuellen Systemzeit. Holen Sie sich seconds_behind_master

Wenn die Systemzeiteinstellungen der Master- und Backup-Datenbankmaschinen inkonsistent sind, führt dies nicht dazu, dass die Master- und Backup-Verzögerungswerte ungenau sind. Wenn die Standby-Datenbank mit der Primärdatenbank verbunden ist, erhält sie die Systemzeit der aktuellen Primärdatenbank über die Funktion SELECTUNIX_TIMESTAMP(). Wenn zu diesem Zeitpunkt festgestellt wird, dass die Systemzeit der Hauptdatenbank nicht mit ihrer eigenen übereinstimmt, zieht die Standby-Datenbank diese Differenz automatisch ab, wenn sie die Berechnung seconds_behind_master ausführt.

Unter normalen Netzwerkbedingungen ist dies die Hauptverzögerungsquelle zwischen der aktiven und der Standby-Datenbank Datenbanken ist die Zeit, nachdem die Standby-Datenbank das Binlog empfangen und die Ausführung abgeschlossen hat der Hauptdatenbank, die Binlog erstellt

2. Der ursprüngliche Grund für die Master-Backup-Verzögerung

1 Unter Bereitstellungsbedingungen ist die Leistung der Maschine, auf der sich die Standby-Datenbank befindet, schlechter Hauptdatenbank befindet sich 2. Die Standby-Datenbank steht unter größerem Druck. Die Hauptdatenbank bietet Schreibfunktionen und die Standby-Datenbank bietet einige Lesefunktionen. Wenn die Drucksteuerung der Standby-Datenbank ignoriert wird, verbraucht die Abfrage in der Standby-Datenbank viele CPU-Ressourcen, wirkt sich auf die Synchronisierungsgeschwindigkeit aus und führt zu Verzögerungen zwischen Master und Backup. Die folgende Verarbeitung kann durchgeführt werden:

Ein Master und mehrere Sklaven. Zusätzlich zur Standby-Datenbank können Sie mehrere weitere Slave-Datenbanken verbinden, um den Lesedruck zu teilen.

Ausgabe an externe Systeme über Binlog, z. B. Hadoop, sodass das externe System statistische Abfragefunktionen bereitstellen kann. Denn die Hauptdatenbank muss auf die Ausführung der Transaktion warten, bevor sie in das Binlog geschrieben und dann an die Standby-Datenbank übergeben wird. Wenn daher eine Anweisung in der Hauptdatenbank 10 Minuten lang ausgeführt wird, verursacht diese Transaktion wahrscheinlich eine Verzögerung von 10 Minuten in der Slave-Datenbank. Typisches Szenario für große Transaktionen: Verwenden der Löschanweisung zum Löschen zu vieler Daten und DDL von a große Tabelle auf einmal

    4. Master-/Backup-Umschaltstrategie
  • 1. Zuverlässigkeitsprioritätsstrategie

Unter der Doppel-M-Struktur ist der detaillierte Prozess des Umschaltens von Zustand 1 auf Zustand 2 wie folgt:

1 . Bestimmen Sie den aktuellen seconds_behind_master der Standby-Datenbank B. Wenn dieser kleiner als ein bestimmter Wert ist, fahren Sie mit dem nächsten Schritt fort, andernfalls wiederholen Sie diesen Schritt.

2 Ändern Sie die Hauptbibliothek A in einen schreibgeschützten Zustand , setzen Sie readonly auf true

3. Bestimmen Sie den Wert von seconds_behind_master der Standby-Bibliothek B, bis dieser Wert 0 wird

4. Ändern Sie die Standby-Datenbank B in einen Lese-/Schreibstatus, dh setzen Sie readonly auf false

5. Schalten Sie die Geschäftsanfrage auf die Standby-Datenbank B

Gibt es bei diesem Umschaltvorgang eine zeitliche Nichtverfügbarkeit? Nach Schritt 2 befinden sich sowohl die Hauptdatenbank A als auch die Standby-Datenbank B im schreibgeschützten Zustand, was bedeutet, dass sich das System in einem nicht beschreibbaren Zustand befindet und nicht wiederhergestellt werden kann, bis Schritt 5 abgeschlossen ist. In diesem nicht verfügbaren Zustand ist Schritt 3 der zeitaufwendigere Schritt, der mehrere Sekunden dauern kann. Aus diesem Grund müssen wir in Schritt 1 zunächst eine Beurteilung vornehmen, um sicherzustellen, dass der Wert von seconds_behind_master klein genug ist. Die Nichtverfügbarkeitszeit des Systems wird durch diese Prioritätsstrategie für die Datenzuverlässigkeit bestimmt Verfügbarkeitsprioritätsstrategie: Passen Sie die Schritte 4 und 5 der Zuverlässigkeitsprioritätsstrategie zwangsweise so an, dass sie gleich zu Beginn ausgeführt werden, dh ohne auf die Synchronisierung der Haupt- und Sicherungsdaten zu warten, und schalten Sie die Verbindung direkt zur Standby-Datenbank B um Wenn Sie der Standby-Datenbank B das Lesen und Schreiben ermöglichen, treten im System nahezu keine Probleme auf. Der Preis dieses Wechselvorgangs besteht darin, dass es zu Dateninkonsistenzen kommen kann. Tabelle t definiert eine automatisch inkrementierende Primärschlüssel-ID. Nach der Initialisierung der Daten gibt es drei Datenzeilen in der Hauptdatenbank und der Standby-Datenbank. Führen Sie weiterhin zwei Einfügungsbefehle für Tabelle t aus, in der folgenden Reihenfolge:

mysql> CREATE TABLE `t` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `c` int(11) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`)) ENGINE=InnoDB;insert into t(c) values(1),(2),(3);
Nach dem Login kopieren

Angenommen, es gibt eine große Anzahl von Aktualisierungen für andere Datentabellen in der Hauptdatenbank, wodurch die Haupt-Standby-Verzögerung 5 Sekunden erreicht. Nach dem Einfügen einer Anweisung mit c=4 wird die Aktiv/Standby-Umschaltung eingeleitet

Die folgende Abbildung zeigt die Verfügbarkeitsprioritätsstrategie sowie den Umschaltprozess und die Datenergebnisse, wenn binlog_format=mixed

1. In Schritt 2 wird die Hauptbibliothek A abgeschlossen Die Einfügeanweisung, das Einfügen einer Datenzeile (4,4) und das anschließende Starten des Aktiv-Standby-Schalters

2 In Schritt 3 hatte die Standby-Datenbank B aufgrund der 5-Sekunden-Verzögerung keine Zeit Zeit, das Einfügen von c=4 anzuwenden. Nach der Übertragung des Protokolls beginnt es, den Befehl des Clients zum Einfügen von c=5Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
3 zu empfangen. In Schritt 4 fügt die Standby-Datenbank B eine Datenzeile (4,5) ein und sendet diese binlog zur Hauptdatenbank A

4. Schritt 5: Die Standby-Datenbank B führt das Einfügen des Übertragungsprotokolls c=4 aus und fügt eine Datenzeile ein (5,4). Die Anweisung insert c=5, die direkt in der Standby-Datenbank B ausgeführt wird, wird an die Hauptdatenbank A übertragen und eine neue Datenzeile (5,5) eingefügt. Das Endergebnis ist, dass zwei Zeilen in der Hauptdatenbank A erscheinen und die Standby-Datenbank B. Zeilen inkonsistenter Daten

Verfügbarkeitsprioritätsstrategie, setze binlog_format=row
Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
Wenn das Zeilenformat binlog aufzeichnet, werden daher alle Feldwerte der neu eingefügten Zeilen aufgezeichnet, sodass am Ende nur eine Zeile inkonsistent ist . Darüber hinaus melden die Anwendungsthreads der aktiven und Standby-Synchronisierung auf beiden Seiten einen Fehler wegen doppeltem Schlüssel und stoppen. Mit anderen Worten, in diesem Fall werden die beiden Datenzeilen (5,4) in der Standby-Datenbank B und (5,5) in der Primärdatenbank A nicht von der anderen Partei ausgeführt

3 Zusammenfassung

1. Bei Verwendung von Binlog im Zeilenformat sind Dateninkonsistenzprobleme leichter zu finden. Bei der Verwendung von Binlog im gemischten Format oder im Anweisungsformat kann es lange dauern, bis das Problem der Dateninkonsistenz erkannt wird. Daher wird in den meisten Fällen empfohlen, eine Strategie zu übernehmen, bei der die Zuverlässigkeit an erster Stelle steht

5. Die parallele Replikationsstrategie von MySQL

Worauf Sie achten müssen, sind die beiden schwarzen Pfeile im Bild oben für die Parallele Replikationsfunktionen des primären und sekundären Servers. Einer stellt den Client dar, der in die Hauptdatenbank schreibt, und der andere stellt das sql_thread-Ausführungsübertragungsprotokoll in der Standby-Datenbank dar. Vor MySQL-Version 5.6 unterstützte MySQL nur die Single-Thread-Replikation. Daher traten schwerwiegende Probleme auf, wenn die Hauptdatenbank parallel war waren hoch. Das Haupt- und Backup-Verzögerungsproblem

Der Multithread-Replikationsmechanismus teilt den sql_thread mit nur einem Thread in mehrere Threads auf, was dem folgenden Modell entspricht: Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL

Der Koordinator ist der ursprüngliche sql_thread, aber jetzt ist er nicht mehr vorhanden Aktualisiert die Daten nicht mehr direkt und ist nur noch für das Lesen des Transitprotokolls und die Verteilung von Transaktionen verantwortlich. Was das Protokoll tatsächlich aktualisiert, wird zum Arbeitsthread. Die Anzahl der Worker-Threads wird durch den Parameter „slave_parallel_workers“ bestimmt. Bei der Verteilung muss der Koordinator die folgenden zwei Grundanforderungen erfüllen:

kann keine Update-Abdeckung verursachen. Dies erfordert, dass zwei Transaktionen, die dieselbe Zeile aktualisieren, an denselben Worker verteilt werden müssen. Dieselbe Transaktion kann nicht aufgeteilt werden und muss im selben Worker platziert werden. 1 Parallele Replikationsstrategie von MySQL Version 5.6

Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
MySQL Version 5.6 unterstützt die parallele Replikation, die unterstützte Granularität ist jedoch die parallele Replikation nach Datenbank. In der Hash-Tabelle, die zur Bestimmung der Verteilungsstrategie verwendet wird, ist der Schlüssel der Datenbankname

Der parallele Effekt dieser Strategie hängt vom Druckmodell ab. Wenn in der Hauptdatenbank mehrere Datenbanken vorhanden sind und der Druck jeder Datenbank ausgeglichen ist, ist die Wirkung dieser Strategie sehr gut Bibliotheksname ist erforderlich

    Das Format von binlog ist nicht erforderlich, da Binlog im Anweisungsformat auch problemlos den Bibliotheksnamen erhalten kann
  • Sie können verschiedene DBs erstellen, Tabellen mit derselben Beliebtheit gleichmäßig auf diese verschiedenen DBs verteilen und diese verwenden Strategie erzwungen

2. MariaDBs parallele Replikationsstrategie

Redo-Log-Gruppenübermittlungsoptimierung, und MariaDBs parallele Replikationsstrategie nutzt diese Funktion:

Transaktionen, die in derselben Gruppe übermittelt werden können, ändern definitiv nicht dieselbe Zeile

Master-Transaktionen, die parallel in der Datenbank ausgeführt werden können, müssen auch parallel in der Standby-Datenbank ausgeführt werden. In Bezug auf die Implementierung führt MariaDB Folgendes aus:

    1. Transaktionen, die zusammen in einer Gruppe übermittelt werden, haben die gleiche commit_id Gruppe ist commit_id+1
  • 2. Commit_id wird direkt in das Binlog geschrieben
  • 3 Bei der Übertragung an die Standby-Datenbankanwendung werden Transaktionen mit derselben commit_id nach allen Ausführungen dieser Gruppe an mehrere Worker verteilt Wenn die Transaktion abgeschlossen ist, holt der Koordinator einen Stapel ab

Die folgende Abbildung geht von der Ausführung von drei Transaktionssätzen in der Hauptbibliothek aus. Wenn trx1, trx2 und trx3 übermittelt werden, werden trx4, trx5 und trx6 ausgeführt. Auf diese Weise wird, wenn die erste Gruppe von Transaktionen übermittelt wird, die nächste Gruppe von Transaktionen bald in den Commit-Status wechseln

Gemäß der parallelen Replikationsstrategie von MariaDB ist der Ausführungseffekt auf die Standby-Datenbank wie folgt:

  • Im Standby-Modus Bei der Ausführung in der Bibliothek muss die zweite Gruppe von Transaktionen warten, bis die erste Gruppe von Transaktionen vollständig ausgeführt ist, sodass der Systemdurchsatz nicht ausreicht.
  • Darüber hinaus wird diese Lösung durch große Transaktionen leicht behindert. Unter der Annahme, dass trx2 eine sehr große Transaktion ist, kann die nächste Gruppe mit der Ausführung beginnen, wenn die Standby-Datenbank angewendet wird und die Ausführung von trx1 und trx3 abgeschlossen ist. Es funktioniert nur ein Arbeitsthread, was eine Verschwendung von Ressourcen darstellt
  • Konfiguriert als DATABASE bedeutet die Verwendung der Datenbank-für-Datenbank-Parallelstrategie von MySQL 5.6 Version

konfiguriert als LOGICAL_CLOCK, was eine ähnliche Strategie wie MariaDB bedeutet. MySQL wurde auf dieser Basis optimiert. Können alle Transaktionen, die sich gleichzeitig im Ausführungszustand befinden, parallelisiert werden?

不可以,因为这里面可能有由于锁冲突而处于锁等待状态的事务。如果这些事务在备库上被分配到不同的worker,就会出现备库跟主库不一致的情况

而MariaDB这个策略的核心是所有处于commit状态的事务可以并行。事务处于commit状态表示已经通过了锁冲突的检验了
Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
其实只要能够达到redo log prepare阶段就表示事务已经通过锁冲突的检验了

因此,MySQL5.7并行复制策略的思想是:

1.同时处于prepare状态的事务,在备库执行时是可以并行的

2.处于prepare状态的事务,与处于commit状态的事务之间,在备库执行时也是可以并行的

binlog组提交的时候有两个参数:

  • binlog_group_commit_sync_delay参数表示延迟多少微妙后才调用fsync
  • binlog_group_commit_sync_no_delay_count参数表示基类多少次以后才调用fsync

这两个参数是用于故意拉长binlog从write到fsync的时间,以此减少binlog的写盘次数。在MySQL5.7的并行复制策略里,它们可以用来制造更多的同时处于prepare阶段的事务。这样就增加了备库复制的并行度。也就是说,这两个参数既可以故意让主库提交得慢些,又可以让备库执行得快些

4、MySQL5.7.22的并行复制策略

MySQL5.7.22增加了一个新的并行复制策略,基于WRITESET的并行复制,新增了一个参数binlog-transaction-dependency-tracking用来控制是否启用这个新策略。这个参数的可选值有以下三种:

  • COMMIT_ORDER,根据同时进入prepare和commit来判断是否可以并行的策略
  • WRITESET,表示的是对于事务涉及更新的每一行,计算出这一行的hash值,组成集合writeset。如果两个事务没有操作相同的行,也就是说它们的writeset没有交集,就可以并行
  • WRITESET_SESSION,是在WRITESET的基础上多了一个约束,即在主库上同一个线程先后执行的两个事务,在备库执行的时候,要保证相同的先后顺序

为了唯一标识,hash值是通过库名+表名+索引名+值计算出来的。如果一个表上除了有主键索引外,还有其他唯一索引,那么对于每个唯一索引,insert语句对应的writeset就要多增加一个hash值

1.writeset是在主库生成后直接写入到binlog里面的,这样在备库执行的时候不需要解析binlog内容

2.不需要把整个事务的binlog都扫一遍才能决定分发到哪个worker,更省内存

3.由于备库的分发策略不依赖于binlog内容,索引binlog是statement格式也是可以的

对于表上没主键和外键约束的场景,WRITESET策略也是没法并行的,会暂时退化为单线程模型

六、主库出问题了,从库怎么办?

下图是一个基本的一主多从结构

Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
图中,虚线箭头表示的是主备关系,也就是A和A’互为主备,从库B、C、D指向的是主库A。一主多从的设置,一般用于读写分离,主库负责所有的写入和一部分读,其他的读请求则由从库分担
Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
一主多从结构在切换完成后,A’会成为新的主库,从库B、C、D也要改接到A’

1、基于位点的主备切换

当我们把节点B设置成节点A’的从库的时候,需要执行一条change master命令:

CHANGE MASTER TO 
MASTER_HOST=$host_name 
MASTER_PORT=$port 
MASTER_USER=$user_name 
MASTER_PASSWORD=$password 
MASTER_LOG_FILE=$master_log_name 
MASTER_LOG_POS=$master_log_pos
Nach dem Login kopieren
  • MASTER_HOST、MASTER_PORT、MASTER_USER和MASTER_PASSWORD四个参数,分别代表了主库A’的IP、端口、用户名和密码
  • 最后两个参数MASTER_LOG_FILE和MASTER_LOG_POS表示,要从主库的master_log_name文件的master_log_pos这个位置的日志继续同步。而这个位置就是所说的同步位点,也就是主库对应的文件名和日志偏移量

找同步位点很难精确取到,只能取一个大概位置。一种去同步位点的方法是这样的:

1.等待新主库A’把中转日志全部同步完成

2.在A’上执行show master status命令,得到当前A’上最新的File和Position

3.取原主库A故障的时刻T

4.用mysqlbinlog工具解析A’的File,得到T时刻的位点,这个值就可以作为$master_log_pos

这个值并不精确,有这么一种情况,假设在T这个时刻,主库A已经执行完成了一个insert语句插入了一行数据R,并且已经将binlog传给了A’和B,然后在传完的瞬间主库A的主机就掉电了。那么,这时候系统的状态是这样的:

1.在从库B上,由于同步了binlog,R这一行已经存在

2.在新主库A’上,R这一行也已经存在,日志是写在master_log_pos这个位置之后的

3.在从库B上执行change master命令,指向A’的File文件的master_log_pos位置,就会把插入R这一行数据的binlog又同步到从库B去执行,造成主键冲突,然后停止tongue

通常情况下,切换任务的时候,要先主动跳过这些错误,有两种常用的方法

一种是,主动跳过一个事务

set global sql_slave_skip_counter=1;start slave;
Nach dem Login kopieren

另一种方式是,通过设置slave_skip_errors参数,直接设置跳过指定的错误。这个背景是,我们很清楚在主备切换过程中,直接跳过这些错误是无损的,所以才可以设置slave_skip_errors参数。等到主备间的同步关系建立完成,并稳定执行一段时间之后,还需要把这个参数设置为空,以免之后真的出现了主从数据不一致,也跳过了

2、GTID

MySQL5.6引入了GTID,是一个全局事务ID,是一个事务提交的时候生成的,是这个事务的唯一标识。它的格式是:

GTID=source_id:transaction_id
Nach dem Login kopieren
  • source_id是一个实例第一次启动时自动生成的,是一个全局唯一的值
  • transaction_id是一个整数,初始值是1,每次提交事务的时候分配给这个事务,并加1

GTID模式的启动只需要在启动一个MySQL实例的时候,加上参数gtid_mode=on和enforce_gtid_consistency=on就可以了

在GTID模式下,每个事务都会跟一个GTID一一对应。这个GTID有两种生成方式,而使用哪种方式取决于session变量gtid_next的值

1.如果gtid_next=automatic,代表使用默认值。这时,MySQL就把GTID分配给这个事务。记录binlog的时候,先记录一行SET@@SESSION.GTID_NEXT=‘GTID’。把这个GTID加入本实例的GTID集合

2.如果gtid_next是一个指定的GTID的值,比如通过set gtid_next=‘current_gtid’,那么就有两种可能:

  • 如果current_gtid已经存在于实例的GTID集合中,接下里执行的这个事务会直接被系统忽略
  • 如果current_gtid没有存在于实例的GTID集合中,就将这个current_gtid分配给接下来要执行的事务,也就是说系统不需要给这个事务生成新的GTID,因此transaction_id也不需要加1

一个current_gtid只能给一个事务使用。这个事务提交后,如果要执行下一个事务,就要执行set命令,把gtid_next设置成另外一个gtid或者automatic

这样每个MySQL实例都维护了一个GTID集合,用来对应这个实例执行过的所有事务

3、基于GTID的主备切换

在GTID模式下,备库B要设置为新主库A’的从库的语法如下:

CHANGE MASTER TO MASTER_HOST=$host_name 
MASTER_PORT=$port 
MASTER_USER=$user_name 
MASTER_PASSWORD=$password 
master_auto_position=1
Nach dem Login kopieren

其中master_auto_position=1就表示这个主备关系使用的是GTID协议

实例A’的GTID集合记为set_a,实例B的GTID集合记为set_b。我们在实例B上执行start slave命令,取binlog的逻辑是这样的:

1.实例B指定主库A’,基于主备协议建立连接

2.实例B把set_b发给主库A’

3.实例A’算出set_a与set_b的差集,也就是所有存在于set_a,但是不存在于set_b的GTID的集合,判断A’本地是否包含了这个差集需要的所有binlog事务

  • 如果不包含,表示A’已经把实例B需要的binlog给删掉了,直接返回错误
  • 如果确认全部包含,A’从自己的binlog文件里面,找出第一个不在set_b的事务,发给B

4.之后从这个事务开始,往后读文件,按顺序取binlog发给B去执行

4、GTID和在线DDL

如果是由于索引缺失引起的性能问题,可以在线加索引来解决。但是,考虑到要避免新增索引对主库性能造成的影响,可以先在备库加索引,然后再切换,在双M结构下,备库执行的DDL语句也会传给主库,为了避免传回后对主库造成影响,要通过set sql_log_bin=off关掉binlog,但是操作可能会导致数据和日志不一致

两个互为主备关系的库实例X和实例Y,且当前主库是X,并且都打开了GTID模式。这时的主备切换流程可以变成下面这样:

  • 在实例X上执行stop slave
  • 在实例Y上执行DDL语句。这里不需要关闭binlog
  • 执行完成后,查出这个DDL语句对应的GTID,记为source_id_of_Y:transaction_id
  • 到实例X上执行一下语句序列:
set GTID_NEXT="source_id_of_Y:transaction_id";begin;commit;set gtid_next=automatic;start slave;
Nach dem Login kopieren

这样做的目的在于,既可以让实例Y的更新有binlog记录,同时也可以确保不会在实例X上执行这条更新

七、MySQL读写分离

读写分离的基本结构如下图:

Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
读写分离的主要目的就是分摊主库的压力。上图中的结构是客户端主动做负载均衡,这种模式下一般会把数据库的连接信息放在客户端的连接层。由客户端来选择后端数据库进行查询

还有一种架构就是在MySQL和客户端之间有一个中间代理层proxy,客户端只连接proxy,由proxy根据请求类型和上下文决定请求的分发路由
Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
1.客户端直连方案,因此少了一层proxy转发,所以查询性能稍微好一点,并且整体架构简单,排查问题更方便。但是这种方案,由于要了解后端部署细节,所以在出现主备切换、库迁移等操作的时候,客户端都会感知到,并且需要调整数据库连接信息。一般采用这样的架构,一定会伴随一个负责管理后端的组件,比如Zookeeper,尽量让业务端只专注于业务逻辑开发

2.带proxy的架构,对客户端比较友好。客户端不需要关注后端细节,连接维护、后端信息维护等工作,都是由proxy完成的。但这样的话,对后端维护团队的要求会更高,而且proxy也需要有高可用架构

在从库上会读到系统的一个过期状态的现象称为过期读

1、强制走主库方案

强制走主库方案其实就是将查询请求做分类。通常情况下,可以分为这么两类:

1.对于必须要拿到最新结果的请求,强制将其发到主库上

2.对于可以读到旧数据的请求,才将其发到从库上

这个方案最大的问题在于,有时候可能会遇到所有查询都不能是过期读的需求,比如一些金融类的业务。这样的话,就需要放弃读写分离,所有读写压力都在主库,等同于放弃了扩展性

2、Sleep方案

主库更新后,读从库之前先sleep一下。具体的方案就是,类似于执行一条select sleep(1)命令。这个方案的假设是,大多数情况下主备延迟在1秒之内,做一个sleep可以很大概率拿到最新的数据

以买家发布商品为例,商品发布后,用Ajax直接把客户端输入的内容作为最新商品显示在页面上,而不是真正地去数据库做查询。这样,卖家就可以通过这个显示,来确认产品已经发布成功了。等到卖家再刷新页面,去查看商品的时候,其实已经过了一段时间,也就达到了sleep的目的,进而也就解决了过期读的问题

但这个方案并不精确:

1.如果这个查询请求本来0.5秒就可以在从库上拿到正确结果,也会等1秒

2.如果延迟超过1秒,还是会出现过期读

3、判断主备无延迟方案

show slave status结果里的seconds_behind_master参数的值,可以用来衡量主备延迟时间的长短

1.第一种确保主备无延迟的方法是,每次从库执行查询请求前,先判断seconds_behind_master是否已经等于0。如果还不等于0,那就必须等到这个参数变为0才能执行查询请求

show slave status结果的部分截图如下:

Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
2.第二种方法,对比位点确保主备无延迟:

  • Master_Log_File和Read_Master_Log_Pos表示的是读到的主库的最新位点
  • Relay_Master_Log_File和Exec_Master_Log_Pos表示的是备库执行的最新位点

如果Master_Log_File和Read_Master_Log_Pos和Relay_Master_Log_File和Exec_Master_Log_Pos这两组值完全相同,就表示接收到的日志已经同步完成

3.第三种方法,对比GTID集合确保主备无延迟:

  • Auto_Position=1表示这堆主备关系使用了GTID协议
  • Retrieved_Gitid_Set是备库收到的所有日志的GTID集合
  • Executed_Gitid_Set是备库所有已经执行完成的GTID集合

如果这两个集合相同,也表示备库接收到的日志都已经同步完成

4.一个事务的binlog在主备库之间的状态:

1)主库执行完成,写入binlog,并反馈给客户端

2)binlog被从主库发送给备库,备库收到

3)在备库执行binlog完成

上面判断主备无延迟的逻辑是备库收到的日志都执行完成了。但是,从binlog在主备之间状态的分析中,有一部分日志,处于客户端已经收到提交确认,而备库还没收到日志的状态
Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
这时,主库上执行完成了三个事务trx1、trx2和trx3,其中:

  • trx1和trx2已经传到从库,并且已经执行完成了
  • trx3在主库执行完成,并且已经回复给客户端,但是还没有传到从库中

如果这时候在从库B上执行查询请求,按照上面的逻辑,从库认为已经没有同步延迟,但还是查不到trx3的

4、配合semi-sync

要解决上面的问题,就要引入半同步复制。semi-sync做了这样的设计:

1.事务提交的时候,主库把binlog发送给从库

2.从库收到binlog以后,发回给主库一个ack,表示收到了

3.主库收到这个ack以后,才能给客户端返回事务完成的确认

如果启用了semi-sync,就表示所有给客户端发送过确认的事务,都确保了备库已经收到了这个日志

semi-sync+位点判断的方案,只对一主一备的场景是成立的。在一主多从场景中,主库只要等到一个从库的ack,就开始给客户端返回确认。这时,在从库上执行查询请求,就有两种情况:

1.如果查询是落在这个响应了ack的从库上,是能够确保读到最新数据

2.但如果查询落到其他从库上,它们可能还没有收到最新的日志,就会产生过期读的问题

判断同步位点的方案还有另外一个潜在的问题,即:如果在业务更新的高峰期,主库的位点或者GTID集合更新很快,那么上面的两个位点等值判断就会一直不成立,很有可能出现从库上迟迟无法响应查询请求的情况
Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
上图从状态1到状态4,一直处于延迟一个事务的状态。但是,其实客户端是在发完trx1更新后发起的select语句,我们只需要确保trx1已经执行完成就可以执行select语句了。也就是说,如果在状态3执行查询请求,得到的就是预期结果了

semi-sync配合主备无延迟的方案,存在两个问题:

1.一主多从的时候,在某些从库执行查询请求会存在过期读的现象

2.在持续延迟的情况下,可能出现过度等待的问题

5、等主库位点方案

select master_pos_wait(file, pos[, timeout]);
Nach dem Login kopieren

这条命令的逻辑如下:

1.它是在从库执行的

2.参数file和pos指的是主库上的文件名和位置

3.timeout可选,设置为正整数N表示这个函数最多等待N秒

这个命令正常返回的结果是一个正整数M,表示从命令开始执行,到应用完file和pos表示的binlog位置,执行了多少事务

1.如果执行期间,备库同步线程发生异常,则返回NULL

2.如果等待超过N秒,就返回-1

3.如果刚开始执行的时候,就发现已经执行过这个位置了,则返回0
Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL
对于上图中先执行trx1,再执行一个查询请求的逻辑,要保证能够查到正确的数据,可以使用这个逻辑:

1.trx1事务更新完成后,马上执行show master status得到当前主库执行到的File和Position

2.选定一个从库执行查询语句

3.在从库上执行select master_pos_wait(file, pos, 1)

4.如果返回值是>=0的正整数,则在这个从库执行查询语句

5.否则,到主库执行查询语句

流程如下:
Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL

6、GTID方案

 select wait_for_executed_gtid_set(gtid_set, 1);
Nach dem Login kopieren

这条命令的逻辑如下:

1.等待,直到这个库执行的事务中包含传入的gtid_set,返回0

2.超时返回1

等主库位点方案中,执行完事务后,还要主动去主库执行show master status。而MySQL5.7.6版本开始,允许在执行完更新类事务后,把这个事务的GTID返回给客户端,这样等GTID的方案可以减少一次查询

等GTID的流程如下:

1.trx1事务更新完成后,从返回包直接获取这个事务的GTID,记为gtid1

2.选定一个从库执行查询语句

3. Führen Sie select wait_for_executed_gtid_set(gtid1, 1);

4 aus. Wenn der Rückgabewert 0 ist, führen Sie die Abfrageanweisung in dieser Slave-Bibliothek aus.


Erfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL Weitere Programmierkenntnisse finden Sie unter:

Einführung in die Programmierung

! !

Das obige ist der detaillierte Inhalt vonErfahren Sie mehr über die Master-Standby-, Master-Slave- und Lese-Schreib-Trennung in MySQL. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:csdn.net
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage