Hintergrund: Als DBA werden die meisten DDL-Änderungen an großen Tabellen mit Perconas pt-online-schema-change durchgeführt. Dieser Artikel erklärt die Verwendung eines anderen Tools, gh-ost: Es ist nicht auf Trigger angewiesen, da es den Slave simuliert, inkrementelle Änderungen im Zeilen-Binlog erhält und diese dann asynchron auf die Ghost-Tabelle anwendet. Bevor Sie gh-ost verwenden, können Sie zunächst den Artikel zum GitHub Open Source MySQL Online-Schemaänderungstool [Übertragung] oder die offizielle Website lesen, um dessen Funktionen und Prinzipien zu verstehen. Dieser Artikel erklärt lediglich die Verwendung. veranschaulichen: 1) Herunterladen und installieren: https://github.com/github/gh-ost/tags 2) Parameterbeschreibung: gh-ost --help Verwendung von gh-ost: --aliyun-rds: Gibt an, ob die Ausführung in der Alibaba Cloud-Datenbank erfolgen soll. WAHR --allow-master-master: Gibt an, ob gh-ost in einer Dual-Master-Replikationsarchitektur ausgeführt werden darf. Wird im Allgemeinen zusammen mit dem Parameter -assume-master-host verwendet. --allow-nullable-unique-key: Erlaubt gh-ost, den eindeutigen Schlüssel, von dem die Datenmigration abhängt, als NULL zuzulassen. Standardmäßig sind eindeutige NULL-Schlüssel nicht zulässig. Wenn der eindeutige Schlüssel, auf den sich die Datenmigration stützt, NULL-Werte zulässt, können falsche Daten entstehen. Gehen Sie daher mit Vorsicht damit um. --allow-on-master: Erlaubt, dass gh-ost direkt auf dem Master ausgeführt wird. Der Standard-Slave, mit dem sich gh-ost verbindet. --alter string:DDL-Anweisung --approve-renamed-columns ALTER: Wenn Sie den Namen einer Spalte ändern, erkennt gh-ost dies und fragt nach einem Grund für die Spaltenumbenennung. Standardmäßig fährt gh-ost nicht fort, es sei denn, Sie geben --approve-renamed-columns ALTER an. --ask-pass:MySQL-Passwort --assume-master-host string:Geben Sie eine Masterdatenbank für gh-ost im Format „IP:Port“ oder „Hostname:Port“ an. Dies ist in einer Master-Master-Architektur nützlich oder wenn gh-ost den Master nicht finden kann. --assume-rbr: Wenn binlog_format=ROW für die Datenbankinstanz festgelegt ist, mit der gh-ost verbunden ist, können Sie -assume-rbr angeben. Dadurch wird verhindert, dass „Stop Slave“ und „Start Slave“ auf dem Slave ausgeführt werden, und der gh-ost-Benutzer benötigt zum Ausführen nicht das SUPER-Privileg. --check-flag --chunk-size int: Anzahl der in jeder Iteration zu verarbeitenden Zeilen (zulässiger Bereich: 100–100000), Standardwert ist 1000. --concurrent-rowcount: Wenn dieser Parameter True (Standard) ist, schätzt gh-ost nach dem Kopieren der Zeilen die Anzahl der Zeilen (mit „explain select count(*)“) und passt die ETA an. Andernfalls schätzt gh-ost zuerst die Anzahl der Zeilen und beginnt dann mit dem Kopieren der Zeilen. --conf string: Pfad der gh-ost-Konfigurationsdatei. --critical-load string: Eine durch Kommas getrennte Liste von Statusnamen=Werten. Wenn der MySQL-Status die entsprechenden Werte überschreitet, wird gh-ost beendet. -critical-load Threads_connected=20,Connections=1500 bedeutet, dass gh-ost aufgrund der kritischen Belastung der Datenbank angehalten und beendet wird, wenn die Statuswerte in MySQL Threads_connected>20,Connections>1500 sind. Durch Komma getrennter Statusname=Schwellenwert, gleiches Format wie --max-load. Wenn der Status den Schwellenwert überschreitet, gerät die App in Panik und wird beendet. --critical-load-hibernate-seconds int: Wenn die kritische Last erreicht ist, wechselt gh-ost für die angegebene Zeit in den Ruhezustand. Es wird von keinem Server etwas gelesen/geschrieben. --critical-load-interval-millis int: Wenn der Wert 0 ist, wird gh-ost sofort beendet, wenn die kritische Last erreicht ist. Wenn der Wert nicht 0 ist, prüft gh-ost nach -critical-load-interval-millis Sekunden erneut, ob die kritische Last erreicht ist. Wenn die kritische Last nach der zweiten Prüfung immer noch erreicht ist, wird gh-ost beendet. --cut-over string: Wählen Sie den Cutover-Typ: atomar/zweistufig. Der atomare (Standard-) Cutover-Typ verwendet den GitHub-Algorithmus und der zweistufige Typ den Facebook-OSC-Algorithmus. --cut-over-exponential-backoff --cut-over-lock-timeout-seconds int: Die maximale Wartezeit für die Sperre während der Cutover-Phase von gh-ost. Wenn die Sperre abläuft, versucht gh-ost den Cutover erneut. (Standard: 3) --database string: Datenbankname. --debug: Debug-Modus. --default-retries int: Die Anzahl der Wiederholungsversuche verschiedener Vorgänge, bevor eine Panik ausgelöst wird. (Standard ist 60) --discard-foreign-keys: Dieser Parameter ist für eine Tabelle mit Fremdschlüsseln. Wenn gh-ost eine Ghost-Tabelle erstellt, werden keine Fremdschlüssel für die Ghost-Tabelle erstellt. Dieser Parameter ist zum Löschen von Fremdschlüsseln nützlich, sollte ansonsten aber mit Vorsicht verwendet werden. --dml-batch-size int: Batchgröße zum Anwenden von DML-Ereignissen in einer einzelnen Transaktion (Bereich 1–100) (Standard 10) --exact-rowcount: Zählen Sie die Anzahl der Tabellenzeilen genau (mithilfe von select count(*)), um eine genauere Schätzung der Zeit zu erhalten. --execute: führt „alter & migrate table“ tatsächlich aus. Der Standardwert ist „noop“, was bedeutet, dass keine Ausführung erfolgt. Einfach testen und beenden. Wenn Sie möchten, dass die ALTER TABLE-Anweisung tatsächlich in der Datenbank implementiert wird, müssen Sie explizit „-execute“ angeben. --exponential-backoff-max-interval int --force-named-cut-over: Wenn wahr, muss der interaktive Befehl „unpostpone | cut-over“ die migrierte Tabelle benennen. --force-table-names string: Tabellennamenpräfix, das für temporäre Tabellen verwendet werden soll. --heartbeat-interval-millis int: gh-ost-Heartbeat-Frequenzwert, Standard ist 500. --helfen --hooks-hint string: beliebige Nachrichten, die über GH_OST_HOOKS_HINT in Hooks eingefügt werden --hooks-path string: Verzeichnis, in dem Hook-Dateien gespeichert werden (Standard ist leer, d. h. Hooks sind deaktiviert). Der Hook sucht in diesem Verzeichnis nach einer Hook-Datei mit derselben Namenskonvention zur Ausführung. --host Zeichenfolge: MySQL IP/Hostname --initially-drop-ghost-table: Überprüfen und löschen Sie vorhandene Ghost-Tabellen vor dem Ghost-Ost-Vorgang. Dieser Parameter wird nicht empfohlen. Bitte verarbeiten Sie die vorhandene Ghost-Tabelle manuell. Standardmäßig ist dieser Parameter nicht aktiviert und gh-ost beendet den Vorgang. --initially-drop-old-table: Vor dem Gh-Ost-Vorgang die vorhandene alte Tabelle prüfen und löschen. Dieser Parameter wird nicht empfohlen. Bitte verarbeiten Sie die vorhandene Ghost-Tabelle manuell. Standardmäßig ist dieser Parameter nicht aktiviert und gh-ost beendet den Vorgang. --initially-drop-socket-file:gh-ost löscht zwangsweise eine vorhandene Socket-Datei. Dieser Parameter wird nicht empfohlen und kann ein laufendes Ghost-Ost-Programm löschen, was zu DDL-Fehlern führt. --master-password string:MySQL-Masterkennwort --master-user string:MySQL-Masterkonto --max-lag-millis int:Maximale Verzögerungszeit der Master-Slave-Replikation. Wenn die Verzögerungszeit der Master-Slave-Replikation diesen Wert überschreitet, ergreift gh-ost Drosselungsmaßnahmen. Standardwert: 1500 s. --max-load Zeichenfolge: durch Komma getrennter Statusname = Schwellenwert, z. B.: „Threads_running=100,Threads_connected=500“. Wenn der Status den Schwellenwert überschreitet, drosselt die App die Schreibvorgänge. --migrate-on-replica: gh-ost führt die Migration auf der Replik aus, nicht auf dem Master. --nice-ratio float: Die Ruhezeit für jeden Chunk-Zeitraum im Bereich [0,0…100,0]. 0: Keine Ruhezeit in den einzelnen Blockperioden, das heißt, ein Block wird nach dem anderen ausgeführt; 1: Für jede Zeilenkopie zusätzlich 1 Millisekunde ruhen; 0,7: Für jede Zeilenkopie von 10 Millisekunden zusätzlich 7 Millisekunden ruhen. --ok-to-drop-table: Nachdem der Gh-Ost-Vorgang abgeschlossen ist, wird die alte Tabelle gelöscht. Standardmäßig wird die alte Tabelle nicht gelöscht und die Tabelle _tablename_del bleibt bestehen. --panic-flag-file string: Wenn diese Datei erstellt wird, wird gh-ost sofort beendet. --password string: MySQL-Passwort --port int: MySQL-Port, vorzugsweise vom Slave --postpone-cut-over-flag-file string: Wenn diese Datei vorhanden ist, wird die Cut-Over-Phase von gh-ost verschoben und die Daten werden weiterhin repliziert, bis die Datei gelöscht wird. --quiet: Leiser Modus. --replica-server-id uint : Server-ID von gh-ost --replication-lag-query string: Veraltet --serve-socket-file string: Absoluter Pfad zur Socket-Datei von gh-ost. --serve-tcp-port int: Für GH-OST zu verwendender Port. Standardmäßig wird ein geschlossener Port verwendet. --skip-foreign-key-checks: Auf „true“ setzen, wenn Sie sicher sind, dass Ihre Tabelle keine Fremdschlüssel enthält, und die Ghost-Key-Validierung überspringen möchten. --skip-renamed-columns ALTER: Wenn Sie den Namen einer Spalte ändern (z. B. „Spalte ändern“), erkennt gh-ost dies und fragt nach einem Grund für die Spaltenumbenennung. Standardmäßig führt gh-ost den Befehl nicht aus. Dieser Parameter weist gh-ost an, die Migration der Spalte zu überspringen und die umbenannte Spalte als „Don’t Care“-Spalte zu behandeln. Dieser Vorgang ist gefährlich, Sie verlieren alle Werte in der Spalte. --stack: Fehler-Stacktrace hinzufügen. --switch-to-rbr: Weisen Sie gh-ost an, das Binlog-Format des Slave-Repositorys automatisch auf das ROW-Format umzustellen. --table string: Tabellenname --test-on-replica: Testen Sie Gh-Ost auf dem Slave, einschließlich der Datenmigration auf dem Slave. Nachdem die Datenmigration abgeschlossen ist, stoppen Sie den Slave und tauschen Sie die Originaltabelle sofort mit der Ghost-Tabelle aus und tauschen Sie sie dann sofort wieder zurück. Stoppen Sie den Slave weiterhin, damit Sie die beiden Tabellen vergleichen können. --test-on-replica-skip-replica-stop: Wenn -test-on-replica ausgeführt wird, bedeutet dieser Parameter, dass der Slave während des Vorgangs nicht gestoppt werden muss. --throttle-additional-flag-file string: Wenn diese Datei erstellt wird, wird der Gh-Ost-Vorgang sofort beendet. Dieser Parameter kann verwendet werden, wenn mehrere Gh-Ost-Operationen gleichzeitig ausgeführt werden, um eine Datei zu erstellen und alle Gh-Ost-Operationen zu stoppen oder die Datei zu löschen und alle Gh-Ost-Operationen fortzusetzen. --throttle-control-replicas string: Listet alle Slave-Bibliotheken auf, die auf Verzögerungen bei der Master-Slave-Replikation überprüft werden müssen. --throttle-flag-file string: Wenn diese Datei erstellt wird, wird der Gh-Ost-Vorgang sofort beendet. Dieser Parameter eignet sich zur Steuerung eines einzelnen Ghost-Vorgangs. Die Zeichenfolge -throttle-additional-flag-file eignet sich zum Steuern mehrerer Gh-Ost-Operationen. --throttle-http-Zeichenfolge --throttle-query-Zeichenfolge: Abfrage drosseln. Wird einmal pro Sekunde ausgeführt. Wenn der Rückgabewert = 0 ist, ist keine Drosselung erforderlich. Wenn der Rückgabewert > 0 ist, muss eine Drosselung durchgeführt werden. Diese Abfrage wird auf dem migrierten Server ausgeführt. Stellen Sie daher sicher, dass sie leicht ist. --timestamp-old-table: Zeitstempel in alten Tabellennamen verwenden. Dadurch wird die Cross-Migration alter Tabellennamen eindeutig und konfliktfrei. --tungsten: Informiert gh-ost, dass Sie eine Tungsten-Replikationstopologie ausführen. --user string:MYSQL-Benutzer --verbose --Version 3) Gebrauchsanweisung: Voraussetzung ist, dass der für den MySQL-Vorgang erforderliche Binlog-Modus ROW ist. Wenn Sie auf einem Slave testen, müssen Sie auch den ROW-Modus verwenden und log_slave_updates aktivieren. Passen Sie die Parameter bei Bedarf gemäß der obigen Beschreibung an. Umgebung: Master-Bibliothek: 192.168.163.131; Slave-Bibliothek: 192.168.163.130 DDL-Prozess: ① Überprüfen Sie, ob Fremdschlüssel und Auslöser vorhanden sind. ② Überprüfen Sie die Primärschlüsselinformationen der Tabelle. ③ Überprüfen Sie, ob es sich um die Master- oder Slave-Datenbank handelt, ob log_slave_updates aktiviert ist und welche Binlog-Informationen vorliegen. ④ Überprüfen Sie, ob die temporären Tabellen, die mit gho und del enden, vorhanden sind. ⑤ Erstellen Sie eine Tabelle, die mit ghc endet, um Datenmigrationsinformationen und Binlog-Informationen usw. zu speichern – die obige Überprüfungsphase. ⑥ Initialisieren Sie die Stream-Verbindung und fügen Sie Binlog-Listening hinzu – die folgende Migrationsphase. ⑥ Erstellen Sie eine temporäre Tabelle, die mit gho endet, und führen Sie DDL auf der temporären Tabelle aus, die mit gho endet. ⑦ Starten Sie eine Transaktion, schreiben Sie die Quelltabellendaten entsprechend der Primärschlüssel-ID in die Tabelle, die mit gho endet, senden Sie sie ab und wenden Sie Binlog an. --- In der folgenden Umstellungsphase ⑧ Quelltabelle sperren, Tabelle umbenennen: Quelltabelle in Source_del-Tabelle umbenennen, Gho-Tabelle in Quelltabelle. ⑨ Bereinigen Sie die GHC-Tabelle. 1. DDL auf einer einzelnen Instanz: Eine einzelne Instanz entspricht einer Masterdatenbank und der Parameter --allow-on-master und der ROW-Modus müssen aktiviert sein. gh-ost --user="root" --password="root" --host=192.168.163.131 --database="test" --table="t1" --alter="ADD COLUMN cc2 varchar(10),add column cc3 int not null default 0 comment 'test' " --allow-on-master --execute 2. DDL auf dem Master und Slave: Es gibt zwei Möglichkeiten. Eine besteht darin, Daten gemäß Schritt 1 direkt vom Master zum Slave zu synchronisieren. Die andere besteht darin, eine Verbindung zum Slave herzustellen und Daten vom Master zu migrieren (stellen Sie einfach sicher, dass das Binlog des Slaves ROW ist, nicht das des Masters): gh-ost --user="root" --password="root" --host=192.168.163.130 --database="test" --table="t" --initially-drop-old-table --alter="ADD COLUMN y1 varchar(10),add column y2 int not null default 0 comment 'test' " --execute Der Vorgang läuft derzeit etwa wie folgt ab:
Bei der Ausführung von DDL führt die Slave-Datenbank einen Befehl zum Stoppen/Starten des Slaves aus. Wenn Sie sicher sind, dass das Binärprotokoll des Slaves ROW ist, können Sie den Parameter hinzufügen: --assume-rbr. Wenn das Binlog des Slaves nicht ROW ist, können Sie es mit dem Parameter --switch-to-rbr in ROW konvertieren. Zu diesem Zeitpunkt ist zu beachten, dass der Binlog-Modus nach der Ausführung nicht auf den ursprünglichen Wert konvertiert wird. Die Parameter --assume-rbr und --switch-to-rbr können nicht zusammen verwendet werden. 3. Führen Sie einen DDL-Test auf dem Slave durch: gh-ost --user="root" --password="root" --host=192.168.163.130 --database="test" --table="t" --alter="ADD COLUMN abc1 varchar(10),add column abc2 int not null default 0 comment 'test' " --test-on-replica --switch-to-rbr --execute Parameter --test-on-replica: Testen Sie Gh-Ost auf dem Slave, einschließlich der Datenmigration auf dem Slave, Stoppen des Slaves nach Abschluss der Datenmigration und sofortiges Austauschen der Originaltabelle mit der Ghost-Tabelle und anschließendes sofortiges Zurücktauschen. Stoppen Sie den Slave weiterhin, damit Sie die beiden Tabellen vergleichen können. Wenn Sie den Slave nicht stoppen möchten, können Sie den Parameter hinzufügen: --test-on-replica-skip-replica-stop Die oben genannten drei sind Ghost-Ost-Betriebsmodi. Bei den oben genannten Vorgängen wird die temporäre Tabelle am Ende nicht bereinigt und muss manuell bereinigt werden. Wenn die temporäre Tabelle vor der nächsten Ausführung noch vorhanden ist, schlägt die Ausführung fehl. Sie können sie über die folgenden Parameter löschen: --initially-drop-ghost-table: Überprüfen und löschen Sie vorhandene Ghost-Tabellen vor dem Ghost-Ost-Vorgang. Dieser Parameter wird nicht empfohlen. Bitte verarbeiten Sie die vorhandene Ghost-Tabelle manuell. Standardmäßig ist dieser Parameter nicht aktiviert und gh-ost beendet den Vorgang. --initially-drop-old-table: Vor dem Gh-Ost-Vorgang die vorhandene alte Tabelle prüfen und löschen. Dieser Parameter wird nicht empfohlen. Bitte verarbeiten Sie die vorhandene Ghost-Tabelle manuell. Standardmäßig ist dieser Parameter nicht aktiviert und gh-ost beendet den Vorgang. --initially-drop-socket-file:gh-ost löscht zwangsweise eine vorhandene Socket-Datei. Dieser Parameter wird nicht empfohlen und kann ein laufendes Ghost-Ost-Programm löschen, was zu DDL-Fehlern führt. --ok-to-drop-table: Nachdem der Gh-Ost-Vorgang abgeschlossen ist, wird die alte Tabelle gelöscht. Standardmäßig wird die alte Tabelle nicht gelöscht und die Tabelle _tablename_del bleibt bestehen. Es gibt noch einige andere Parameter, wie: --exact-rowcount, --max-lag-millis, --max-load usw. Sie können die Anweisungen oben sehen. Die meisten der häufig verwendeten Parameterbefehle lauten wie folgt: gh-osc --user= --password= --host= --database= --table= --max-load=Threads_running=30, --chunk-size=1000 --serve-socket-file=/tmp/gh-ost.test.sock --exact-rowcount --allow-on-master/--test-on-replica --initially-drop-ghost-table/--initially-drop-old-table/--initially-drop-socket-file --max-lag-millis= --max-load='Threads_running=100,Threads_connected=500' --ok-to-drop-table 4) Zusatzanweisungen: Kündigung, Aussetzung, Geschwindigkeitsbegrenzung gh-ost --user="root" --password="root" --host=192.168.163.131 --database="test" --table="t1" --alter="ADD COLUMN o2 varchar(10),Spalte hinzufügen o1 int nicht null Standard 0 Kommentar 'test' " --exact-rowcount --serve-socket-file=/tmp/gh-ost.t1.sock --panic-flag-file=/tmp/gh-ost.panic.t1.flag --postpone-cut-over-flag-file=/tmp/ghost.postpone.t1.flag --allow-on-master --execute ① Flag-Datei zum Beenden des Vorgangs: --panic-flag-file Erstellen Sie eine Datei, um den Vorgang zu beenden. In diesem Beispiel wird die Datei /tmp/gh-ost.panic.t1.flag erstellt, um das laufende gh-ost zu beenden. Die temporäre Datei muss manuell bereinigt werden. ② Gibt an, dass für die Datei ein Cutover verboten ist, d. h. das Wechseln des Tabellennamens ist verboten und die Datenreplikation wird normal durchgeführt. --postpone-cut-over-flag-file Erstellen Sie eine Datei, um die Umstellung zu verzögern, das heißt, den Umschaltvorgang zu verschieben. In diesem Beispiel wird die Datei /tmp/ghost.postpone.t1.flag erstellt. gh-ost schließt die Zeilenreplikation ab, wechselt aber nicht die Tabellen. Es synchronisiert weiterhin Datenaktualisierungen von der Originaltabelle mit der temporären Tabelle. ③ Der Bediener kann mithilfe des Sockets auf Anforderungen warten und die entsprechenden Parameter ändern, nachdem der Befehl ausgeführt wurde. --serve-socket-file, --serve-tcp-port (standardmäßig deaktiviert) Erstellen Sie eine Socket-Datei zum Abhören und passen Sie die Parameter über die Schnittstelle an. Wenn die Last und die Verzögerung während des Vorgangs zunehmen, muss der Vorgang beendet und Parameter wie die Chunk-Größe neu konfiguriert werden. Anschließend kann der Vorgangsbefehl erneut ausgeführt werden. Dynamische Anpassungen können über die Socket-Schnittstelle vorgenommen werden. wie: Betrieb pausieren: # Echo-Drosselung anhalten | socat - /tmp/gh-ost.test.t1.sock #Echo ohne Drosselung fortsetzen | socat - /tmp/gh-ost.test.t1.sock Ändern Sie die Geschwindigkeitsbegrenzungsparameter: echo chunk-size=100 | socat - /tmp/gh-ost.t1.sock echo max-lag-millis=200 | socat - /tmp/gh-ost.t1.sock echo max-load=Thread_running=3 | socat - /tmp/gh-ost.t1.sock 4) Vergleichstest mit pt-online-schema-change 1. Wenn die Tabelle nicht geschrieben wird und die Parameter Standard sind, ist die DDL-Operationszeit der beiden ähnlich, schließlich handelt es sich bei beiden um Operationen zum Kopieren von Zeilen. 2. Wenn viele Schreibvorgänge in die Tabelle erfolgen (Sysbench), ist pt-osc mehrfädig und kann schnell ausgeführt werden, während gh-ost eine einfädige Anwendung simuliert. In extremen Fällen sind DDL-Operationen sehr schwierig abzuschließen. Fazit: Obwohl pt-osc keine Trigger erfordert und den Druck und die Leistung der Hauptdatenbank viel weniger beeinflusst, ist die Effizienz von DDL in Szenarien mit hoher Parallelität immer noch geringer als die von pt-osc, sodass es immer noch während der Geschäftszeiten mit geringer Spitzenlast verarbeitet werden muss. Verwandte Tests finden Sie im Leistungsvergleich zwischen gh-ost und pt-osc. 5) Kapselungsskript: Umgebung: M: 192.168.163.131 (ROW), S: 192.168.163.130/132 Wrapper-Skript: gh-ost.py #!/bin/env python # -*- Kodierung: utf-8 -*- #---------------------------------------------- # Zweck: gh-ost # Erstellt: 2018-06-16 #---------------------------------------------- MySQLdb importieren erneut importieren System importieren Importzeit Unterprozess importieren Betriebssystem importieren von optparse importiere OptionParser def calc_time(Funktion): def _deco(*args, **kwargs): begin_time = Zeit.Zeit() Funktion(*args, **kwargs) Kostenzeit = Zeit.Zeit() - Beginnzeit drucken 'Kostenzeit: %ss' % Runde(Kostenzeit,2) return _deco def get_table_count(conn,dbname,tbname): Abfrage = ''' SELECT count(*) FROM %s.%s ''' %(dbname,tbname) Cursor = conn.cursor() Cursor.Ausführen(Abfrage) Zeilenumbrüche = Cursor.fetchone() cursor.schließen() conn.close() returniere Zeilennummern def online_ddl(conn,ddl_cmd): Cursor = conn.cursor() Cursor.Ausführen(ddl_cmd) conn.commit() cursor.schließen() conn.close() #@Berechnungszeit def run_cmd(cmd): p = Unterprozess.Popen(cmd, shell=True) Rückgabewert p,p.pid auf def drop_ghost_table(conn, ghost_name_list): versuchen: Cursor = conn.cursor() Abfrage = '''Tabelle löschen, wenn %s vorhanden ist; ''' %(Ghost_Name_Liste) Cursor.Ausführen(Abfrage) conn.commit() cursor.schließen() conn.close() außer Ausnahme,e: drucken wenn __name__ == "__main__": parser = OptionParser() parser.add_option("-P", "--Port", help="Port für Suche", dest="Port") parser.add_option("-D", "--Dbname", help="der zu verwendende Datenbankname", dest="Datenbankname") parser.add_option("-T", "--Table", help="die zu verwendende Tabelle", dest="Tabellenname") (Optionen, Argumente) = parser.parse_args() wenn nicht options.port: Drucken Sie „Parameter, die für den Port gelten müssen“ Ausfahrt() wenn nicht options.dbname: print 'Parameter, die für den Datenbanknamen gelten sollen' Ausfahrt() wenn nicht options.tablename: print 'Parameter Tabellenname müssen angewendet werden' Ausfahrt() gh_ost_socket = "/tmp/gh-ost.%s.%s.sock" %(Optionen.DB-Name,Optionen.Tabellenname) #Beendigungsflag panic_flag = '/tmp/gh-ost.panic.%s.%s.flag' %(options.dbname,options.tablename) # shift_flag = '/tmp/gh-ost.shift.%s.%s.flag' %(options.dbname,options.tablename) #Drosselungsflag throttle_flag = '/tmp/gh-ost.throttle.%s.%s' %(options.dbname,options.tablename) # socket = "/data/%s/tmp/mysql.sock" %(Optionen.Port) Socket = "/var/run/mysqld/mysqld.sock" get_conn = MySQLdb.connect(Host='192.168.163.131', Port=int(Optionen.Port), Benutzer='root', Passwort='root', db=Optionen.dbname, Unix_Socket=Socket, Zeichensatz='utf8') conn = MySQLdb.connect(Host='192.168.163.131', Port=int(Optionen.Port), Benutzer='root', Passwort='root', db=Optionen.dbname, Unix_Socket=Socket, Zeichensatz='utf8') (Tabellenanzahl,) = get_table_count(get_conn,Optionen.DBname,Optionen.Tabellenname) print ("\033[0;32m%s\033[0m" % "Anzahl der Tabellen: %s" %table_count) DDL_CMD = raw_input('DDL CMD eingeben: ').replace('`','') gh_command_list = re.split('[ ]+',DDL_CMD) wenn gh_command_list[0].upper() == 'CHANGE' und gh_command_list[1] != gh_command_list[2]: print ("\033[0;31m%s\033[0m" % "Daten umbenannter Spalten gehen verloren, pt-osc exit...") Ausfahrt() wenn table_count <= 10000: ddl = '''ALTER TABLE %s %s ''' %(options.tablename,DDL_CMD) drucken ("\033[0;36m%s\033[0m" %ddl) drucken ("\033[0;32m%s\033[0m" % "online ddl ...") online_ddl(conn,ddl) print ("\033[0;32m%s\033[0m" % "Ausführung abgeschlossen...") Ausfahrt() anders: MAX_LOAD = raw_input('Geben Sie die maximale Anzahl laufender Threads ein【25】: ') wenn nicht MAX_LOAD: Threads_running = 25 anders: versuchen: Ausführende Threads = int(MAXIMALE LAST) außer ValueError: print ("\033[0;31m%s\033[0m" % "Eingabetypfehler, beenden...") Ausfahrt() CHUNK_SIZE = raw_input('Maximale Blockgröße eingeben【1000】: ') wenn nicht CHUNK_SIZE: Blockgröße = 1000 anders: versuchen: Blockgröße = int(CHUNK_SIZE) außer ValueError: print ("\033[0;31m%s\033[0m" % "Eingabetypfehler, beenden...") Ausfahrt() drucken ("\033[0;32m%s\033[0m" % "gh-ost ddl ...") #--postpone-cut-over-flag-file=%s gh_command = '''/usr/bin/gh-ost --user="root" --password="root" --host=192.168.163.131 --port=%s --database="%s" --table="%s" --allow-on-master --max-load='Threads_running=%d' --chunk-size=%d --serve-socket-file=%s --panic-flag-file=%s --throttle-additional-flag-file=%s --alter="%s" --execute ''' %(options.port,options.dbname,options.tablename,Threads_running,chunk_size,gh_ost_socket,panic_flag,throttle_flag,DDL_CMD) drucken ("\033[0;36m%s\033[0m" %gh_Befehl) Kind, PID = run_cmd (gh_command) drucken ("\033[0;31mgh-osts PID: %s\033[0m" %pid) drucken ("\033[0;33mErstellen: [touch %s] Datei, DDL anhalten ...\033[0m" %throttle_flag) versuchen: Kind.warten() außer: Kind.beenden() #sauber ghost_name_list = "_%s_ghc,_%s_gho" %(Optionen.Tabellenname,Optionen.Tabellenname) drop_ghost_table(Verbindung, Geisternamenliste) wenn os.path.exists(gh_ost_socket): os.system('rm -r %s' %gh_ost_socket) print ("\033[0;32m%s\033[0m" % "Reinigung abgeschlossen...") Ausfahrt() print ("\033[0;32m%s\033[0m" % "Reinigung abgeschlossen...") Ausfahrt() Endlich : passieren laufen: root@test2:~# python gh-ost.py -P3306 -Dtest -Tzjy Anzahl Tische: 1310720 Geben Sie DDL CMD ein: ADD COLUMN q1 varchar(10), ADD COLUMN q2 varchar(10) Geben Sie Max Threads_running【25】 ein: 10 Geben Sie die maximale Blockgröße 【1000】 ein: 200 gh-ost ddl … /usr/bin/gh-ost --user="root" --password="root" --host=192.168.163.131 --port=3306 --database="test" --table="zjy" --allow-on-master --max-load='Threads_running=10' --chunk-size=200 --serve-socket-file=/tmp/gh-ost.test.zjy.sock --panic-flag-file=/tmp/gh-ost.panic.test.zjy.flag --throttle-additional-flag-file=/tmp/gh-ost.throttle.test.zjy --alter="ADD COLUMN q1 varchar(10),ADD COLUMN q2 varchar(10)" --execute gh-osts PID: 2105 Erstellen: Datei [touch /tmp/gh-ost.throttle.test.zjy], DDL anhalten … 17.06.2018 14:37:37 binlogsyncer.go:79: [info] BinlogSyncer erstellen mit Konfiguration {99999 mysql 192.168.163.131 3306 root false false <nil>} 17.06.2018 14:37:37 binlogsyncer.go:246: [info] Beginnen Sie mit der Synchronisierung des Binlogs von der Position (mysql-bin.000013, 31197930). 17.06.2018 14:37:37 binlogsyncer.go:139: [info] Slave für Masterserver 192.168.163.131:3306 registrieren 17.06.2018 14:37:37 binlogsyncer.go:573: [info] rotieren nach (mysql-bin.000013, 31197930) # Migriere „test“. „zjy“; Ghost-Tabelle ist „test“. „_zjy_gho“ # Migrieren von test2:3306; Überprüfen von test2:3306; Ausführen auf test2 # Migration gestartet am Sonntag, 17. Juni 2018, 14:37:37 +0800 # Blockgröße: 200; maximale Verzögerung in Milli: 1500 ms; DML-Batchgröße: 10; maximale Auslastung: Threads_running=10; kritische Auslastung:; Nice-Verhältnis: 0,000000 # Drossel-Zusatzflag-Datei: /tmp/gh-ost.throttle.test.zjy # Panik-Flag-Datei: /tmp/gh-ost.panic.test.zjy.flag # Bereitstellung auf Unix-Socket: /tmp/gh-ost.test.zjy.sock Kopie: 0/1305600 0,0 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 0 s (gesamt), 0 s (Kopie); Streamer: mysql-bin.000013:31199542; Status: Migration; ETA: N/A Kopieren: 0/1305600 0,0 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 1 s (gesamt), 1 s (kopieren); Streamer: mysql-bin.000013:31202866; Status: Migration; ETA: N/A Kopieren: 44400/1305600 3,4 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 2 s (gesamt), 2 s (kopieren); Streamer: mysql-bin.000013:33352548; Status: Migration; ETA: 56 s Kopieren: 91200/1305600 7,0 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 3 s (gesamt), 3 s (kopieren); Streamer: mysql-bin.000013:35598132; Status: Migration; ETA: 39 s Kopieren: 135200/1305600 10,4 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 4 s (gesamt), 4 s (kopieren); Streamer: mysql-bin.000013:37727925; Status: Migration; ETA: 34 s Kopieren: 174000/1305600 13,3 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 5 s (gesamt), 5 s (kopieren); Streamer: mysql-bin.000013:39588956; Status: Migration; ETA: 32 s Kopieren: 212200/1305600 16,3 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 6 s (gesamt), 6 s (kopieren); Streamer: mysql-bin.000013:41430090; Status: Migration; ETA: 30 s Kopieren: 254800/1305600 19,5 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 7 s (gesamt), 7 s (kopieren); Streamer: mysql-bin.000013:43483555; Status: Migration; ETA: 28 s Kopie: 303600/1305600 23,3 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 8 s (gesamt), 8 s (Kopie); Streamer: mysql-bin.000013:45834978; Status: Migration; ETA: 26 s Kopie: 351200/1305600 26,9 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 9 s (gesamt), 9 s (Kopie); Streamer: mysql-bin.000013:48128675; Status: Migration; ETA: 24 s Kopieren: 401400/1305600 30,7 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 10 s (gesamt), 10 s (kopieren); Streamer: mysql-bin.000013:50547454; Status: Migration; ETA: 22 s Kopie: 451200/1305600 34,6 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 11 s (gesamt), 11 s (Kopie); Streamer: mysql-bin.000013:52946991; Status: Migration; ETA: 20 s Kopie: 490000/1305600 37,5 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 12 s (gesamt), 12 s (Kopie); Streamer: mysql-bin.000013:54817320; Status: Migration; ETA: 19 s Kopieren: 529600/1305600 40,6 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 13 s (gesamt), 13 s (kopieren); Streamer: mysql-bin.000013:56735431; Status: Migration; ETA: 19 s Kopieren: 589200/1305600 45,1 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 14 s (gesamt), 14 s (kopieren); Streamer: mysql-bin.000013:59606450; Status: Migration; ETA: 17 s Kopieren: 639400/1305600 49,0 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 15 s (gesamt), 15 s (kopieren); Streamer: mysql-bin.000013:62025561; Status: Migration; ETA: 15 s Kopieren: 695200/1305600 53,2 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 16 s (gesamt), 16 s (kopieren); Streamer: mysql-bin.000013:64704138; Status: Migration; ETA: 14 s Kopie: 751200/1305600 57,5 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 17 s (gesamt), 17 s (Kopie); Streamer: mysql-bin.000013:67401961; Status: Migration; ETA: 12 s Kopieren: 803800/1305600 61,6 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 18 s (insgesamt), 18 s (kopieren); Streamer: mysql-bin.000013:69935884; Status: Migration; ETA: 11 s Kopie: 856400/1305600 65,6 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 19 s (gesamt), 19 s (Kopie); Streamer: mysql-bin.000013:72470455; Status: Migration; ETA: 9 s Kopie: 907400/1305600 69,5 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 20 s (gesamt), 20 s (Kopie); Streamer: mysql-bin.000013:74927401; Status: Migration; ETA: 8 s Kopie: 958800/1305600 73,4 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 21 s (gesamt), 21 s (Kopie); Streamer: mysql-bin.000013:77404243; Status: Migration; ETA: 7 s Kopie: 999200/1305600 76,5 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 22 s (gesamt), 22 s (Kopie); Streamer: mysql-bin.000013:79351223; Status: Migration; ETA: 6 s Kopie: 1009600/1305600 77,3 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 23 s (gesamt), 23 s (Kopie); Streamer: mysql-bin.000013:79855229; Status: Migration; ETA: 6 s Kopie: 1059600/1305600 81,2 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 24 s (gesamt), 24 s (Kopie); Streamer: mysql-bin.000013:82264712; Status: Migration; ETA: 5 s Kopie: 1107200/1305600 84,8 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 25 s (gesamt), 25 s (Kopie); Streamer: mysql-bin.000013:84558411; Status: Migration; ETA: 4 s Kopie: 1147000/1305600 87,9 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 26 s (gesamt), 26 s (Kopie); Streamer: mysql-bin.000013:86486148; Status: Migration; ETA: 3 s Kopie: 1198000/1305600 91,8 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 27 s (gesamt), 27 s (Kopie); Streamer: mysql-bin.000013:88943747; Status: Migration; ETA: 2 s Kopie: 1245400/1305600 95,4 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 28 s (gesamt), 28 s (Kopie); Streamer: mysql-bin.000013:91218202; Status: Migration; ETA: 1 s Kopie: 1286600/1305600 98,5 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 29 s (gesamt), 29 s (Kopie); Streamer: mysql-bin.000013:93203991; Status: Migration; ETA: 0 s Kopie: 1310720/1310720 100,0 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 29 s (gesamt), 29 s (Kopie); Streamer: mysql-bin.000013:94366846; Status: Migration; ETA: fällig Kopie: 1310720/1310720 100,0 %; Angewendet: 0; Rückstand: 1/1000; Zeit: 30 s (gesamt), 29 s (Kopie); Streamer: mysql-bin.000013:94369042; Status: Migration; ETA: fällig # Migriere „test“. „zjy“; Ghost-Tabelle ist „test“. „_zjy_gho“ # Migrieren von test2:3306; Überprüfen von test2:3306; Ausführen auf test2 # Migration gestartet am Sonntag, 17. Juni 2018, 14:37:37 +0800 # Blockgröße: 200; maximale Verzögerung in Milli: 1500 ms; DML-Batchgröße: 10; maximale Auslastung: Threads_running=10; kritische Auslastung:; Nice-Verhältnis: 0,000000 # Drossel-Zusatzflag-Datei: /tmp/gh-ost.throttle.test.zjy # Panik-Flag-Datei: /tmp/gh-ost.panic.test.zjy.flag # Bereitstellung auf Unix-Socket: /tmp/gh-ost.test.zjy.sock Kopie: 1310720/1310720 100,0 %; Angewendet: 0; Rückstand: 0/1000; Zeit: 30 s (gesamt), 29 s (Kopie); Streamer: mysql-bin.000013:94371928; Status: Migration; ETA: fällig 17.06.2018 14:38:08 binlogsyncer.go:107: [info] Syncer wird geschlossen … 17.06.2018 14:38:08 binlogstreamer.go:47: [Fehler] Synchronisierung mit Fehler schließen: Synchronisierung wird geschlossen … (Der Fehler hier wirkt sich nicht auf die Verwendung aus, die Synchronisierung wird wiederholt geschlossen, warte auf die Behebung durch den Autor) 17.06.2018 14:38:08 binlogsyncer.go:122: [info] Syncer ist geschlossen # Erledigt Zusammenfassen: gh-ost verzichtet auf Trigger und verwendet Binlog zur Synchronisierung. Als gefälschte Slave-Datenbank kann gh-ost Binärprotokolle aus der Master-/Slave-Datenbank abrufen, filtern und erneut auf die Master-Datenbank anwenden. Dies entspricht dem Anwenden inkrementeller Operationen auf der Master-Datenbank über Binärprotokolle auf die Master-Datenbank selbst, wird jedoch auf Ghost-Tabellen angewendet. gh-ost stellt zuerst eine Verbindung zum Master her, erstellt eine Ghost-Tabelle basierend auf der Alter-Anweisung und stellt dann eine Verbindung als „Slave“ zu einem der echten Slaves her, kopiert die vorhandenen Daten auf dem Master in die Ghost-Tabelle, zieht das Binlog mit den inkrementellen Daten vom Slave und wendet das Binlog dann kontinuierlich wieder auf den Master an. Der Cut-Over in der Abbildung ist der letzte Schritt, der die Quelltabelle der Masterdatenbank sperrt, auf die Anwendung des Binärprotokolls wartet und dann die Ghost-Tabelle durch die Quelltabelle ersetzt. Während der Ausführung fügt gh-ost dem ursprünglichen Binlog-Ereignis die folgenden Hinweise und Heartbeat-Pakete hinzu, um den Fortschritt des gesamten Prozesses zu steuern, den Status zu erkennen usw. Diese Architektur bietet viele Vorteile, beispielsweise:
Das könnte Sie auch interessieren:
|
<<: Wie Sie React forwardRef verwenden und was Sie beachten müssen
>>: CentOS8-Installationstutorial für JDK8/Java8 (empfohlen)
Tutorial zur kostenlosen Konfiguration der mysql ...
Alles ist eine Datei! UNIX hat es bereits gesagt....
Dieser Artikel konzentriert sich hauptsächlich au...
IE10 bietet eine Schaltfläche zum schnellen Lösche...
Konvertierung zwischen RGBA- und Filterwerten unt...
Ich glaube, jeder kennt dieses Gefühl: Ein Video m...
Inhaltsverzeichnis So installieren und konfigurie...
Verwenden Sie CSS3, um das Eingabefeld ähnlich de...
Verwenden Sie js, um den Lichtschalter zu Ihrer R...
In diesem Blog führe ich Sie in einfachen Schritt...
Ein während des Entwicklungsprozesses häufig auft...
Die Hauptkonfigurationsdatei von Nginx ist nginx....
1. CPU-Auslastung sar -p (den ganzen Tag anzeigen...
Inhaltsverzeichnis 1. Was ist Promise 2. Grundleg...
<br />Manchmal werden Ihnen möglicherweise F...