Wenn Sie eine ALTER TABLE-Anweisung in MySQL ausführen, ist die gesamte Tabelle für die Dauer der Anweisung lesesperrend (ermöglicht gleichzeitiges Lesen, verbietet jedoch gleichzeitiges Schreiben). Wenn es sich um eine große Tabelle handelt, können INSERT- oder UPDATE-Anweisungen für eine lange Zeit blockiert werden. Gibt es eine Möglichkeit, eine "heiße Änderung" vorzunehmen, z. B. eine Spalte so hinzuzufügen, dass die Tabelle während des gesamten Prozesses noch aktualisiert werden kann?
Meistens interessiere ich mich für eine Lösung für MySQL, aber ich würde mich für andere RDBMS interessieren, wenn MySQL dies nicht kann.
Zur Verdeutlichung möchte ich lediglich Ausfallzeiten vermeiden, wenn eine neue Funktion, für die eine zusätzliche Tabellenspalte erforderlich ist, in die Produktion verschoben wird. Jedes Datenbankschema wird sich im Laufe der Zeit ändern, das ist nur eine Tatsache des Lebens. Ich verstehe nicht, warum wir akzeptieren sollten, dass diese Änderungen zwangsläufig zu Ausfallzeiten führen müssen. das ist nur schwach.
quelle
Antworten:
Die einzige andere Möglichkeit besteht darin, manuell zu tun, was viele RDBMS-Systeme sowieso tun ...
- Erstellen Sie eine neue Tabelle
Sie können dann den Inhalt der alten Tabelle jeweils über einen Block kopieren. Achten Sie dabei immer auf INSERT / UPDATE / DELETE in der Quelltabelle. (Könnte durch einen Auslöser verwaltet werden. Obwohl dies eine Verlangsamung verursachen würde, ist es keine Sperre ...)
Wenn Sie fertig sind, ändern Sie den Namen der Quelltabelle und dann den Namen der neuen Tabelle. Am besten in einer Transaktion.
Wenn Sie fertig sind, kompilieren Sie alle gespeicherten Prozeduren usw., die diese Tabelle verwenden, neu. Die Ausführungspläne werden wahrscheinlich nicht mehr gültig sein.
BEARBEITEN:
Es wurden einige Kommentare dazu abgegeben, dass diese Einschränkung etwas schlecht ist. Also dachte ich, ich würde es aus einer neuen Perspektive betrachten, um zu zeigen, warum es so ist ...
quelle
Percona erstellt ein Tool namens pt-online-schema-change , mit dem dies durchgeführt werden kann.
Es erstellt im Wesentlichen eine Kopie der Tabelle und ändert die neue Tabelle. Um die neue Tabelle mit dem Original synchron zu halten, werden Trigger zum Aktualisieren verwendet. Auf diese Weise kann auf die ursprüngliche Tabelle zugegriffen werden, während die neue Tabelle im Hintergrund vorbereitet wird.
Dies ähnelt der oben von Dems vorgeschlagenen Methode, erfolgt jedoch automatisiert.
Einige ihrer Tools haben eine Lernkurve, nämlich das Herstellen einer Verbindung zur Datenbank. Sobald Sie diese jedoch nicht mehr haben, sind sie großartige Tools.
Ex:
quelle
Diese Frage aus dem Jahr 2009. Jetzt bietet MySQL eine Lösung:
Online-DDL (Data Definition Language)
Sie können das Gleichgewicht zwischen Leistung und Parallelität während des DDL-Vorgangs anpassen, indem Sie auswählen, ob der Zugriff auf die Tabelle vollständig blockiert werden soll (LOCK = EXCLUSIVE-Klausel), Abfragen, jedoch keine DML (LOCK = SHARED-Klausel) oder vollständige Abfrage und DML zulassen Zugriff auf die Tabelle (LOCK = NONE-Klausel). Wenn Sie die LOCK-Klausel weglassen oder LOCK = DEFAULT angeben, lässt MySQL je nach Art der Operation so viel Parallelität wie möglich zu.
Wenn möglich Änderungen vor Ort vorgenommen werden, anstatt eine neue Kopie der Tabelle zu erstellen, werden vorübergehende Erhöhungen der Speicherplatznutzung und des E / A-Overheads vermieden, die mit dem Kopieren der Tabelle und der Rekonstruktion von Sekundärindizes verbunden sind.
Weitere Informationen finden Sie im MySQL 5.6 Referenzhandbuch -> InnoDB und Online DDL .
Es scheint, dass Online-DDL auch in MariaDB verfügbar ist
MariaDB KB über ALTER TABLE
quelle
Siehe das Online-Schemaänderungstool von Facebook.
http://www.facebook.com/notes/mysql-at-facebook/online-schema-change-for-mysql/430801045932
Nicht für schwache Nerven; aber es wird den Job machen.
quelle
Ich empfehle Postgres, wenn das eine Option ist. Bei Postgres gibt es im Wesentlichen keine Ausfallzeiten mit den folgenden Verfahren:
Ein weiteres großartiges Feature ist, dass die meisten DDL-Anweisungen transaktional sind, sodass Sie eine vollständige Migration innerhalb einer SQL-Transaktion durchführen können. Wenn etwas schief geht, wird das gesamte Ding zurückgesetzt.
Ich schrieb dies ein wenig vor, vielleicht kann er etwas mehr Einblick in den anderen Vorzügen vergießen.
quelle
Da Sie nach anderen Datenbanken gefragt haben, finden Sie hier einige Informationen zu Oracle.
Das Hinzufügen einer NULL-Spalte zu einer Oracle-Tabelle ist ein sehr schneller Vorgang, da nur das Datenwörterbuch aktualisiert wird. Dies hält eine exklusive Sperre für einen sehr kurzen Zeitraum auf dem Tisch. Abhängig gespeicherte Prozeduren, Ansichten, Trigger usw. werden jedoch ungültig. Diese werden automatisch neu kompiliert.
Von dort aus können Sie bei Bedarf mit der ONLINE-Klausel einen Index erstellen. Auch hier werden nur sehr kurze Datenwörterbuchsperren. Es liest die gesamte Tabelle nach zu indizierenden Dingen, blockiert dabei jedoch niemanden.
Wenn Sie einen Fremdschlüssel hinzufügen müssen, können Sie dies tun und Oracle dazu bringen, Ihnen zu vertrauen, dass die Daten korrekt sind. Andernfalls muss die gesamte Tabelle gelesen und alle Werte überprüft werden, die langsam sein können (erstellen Sie zuerst Ihren Index).
Wenn Sie in jede Zeile der neuen Spalte einen Standardwert oder einen berechneten Wert einfügen müssen, müssen Sie ein umfangreiches Update oder möglicherweise ein kleines Hilfsprogramm ausführen, das die neuen Daten auffüllt. Dies kann langsam sein, insbesondere wenn die Zeilen viel größer werden und nicht mehr in ihre Blöcke passen. Das Sperren kann während dieses Vorgangs verwaltet werden. Da der alte Versino Ihrer Anwendung, der noch ausgeführt wird, diese Spalte nicht kennt, benötigen Sie möglicherweise einen hinterhältigen Auslöser oder müssen einen Standard angeben.
Von dort aus können Sie auf Ihren Anwendungsservern auf die neue Version des Codes umschalten und dieser läuft weiter. Lass deinen hinterhältigen Abzug fallen.
Alternativ können Sie DBMS_REDEFINITION verwenden, eine Black Box, die für solche Aufgaben entwickelt wurde.
All dies ist so viel Mühe zu testen usw., dass wir nur einen frühen Ausfall am Sonntagmorgen haben, wenn wir eine Hauptversion veröffentlichen.
quelle
Wenn Sie sich bei Anwendungsaktualisierungen keine Ausfallzeiten für Ihre Datenbank leisten können, sollten Sie einen Cluster mit zwei Knoten für eine hohe Verfügbarkeit in Betracht ziehen. Mit einem einfachen Replikations-Setup können Sie fast vollständig online strukturelle Änderungen vornehmen, wie die von Ihnen vorgeschlagene:
Es ist nicht immer einfach, aber es funktioniert normalerweise mit 0 Ausfallzeiten! Der zweite Knoten muss nicht nur passiv sein, sondern kann zum Testen, Erstellen von Statistiken oder als Fallback-Knoten verwendet werden. Wenn Sie keine Infrastruktur haben, kann die Replikation auf einem einzelnen Computer (mit zwei Instanzen von MySQL) eingerichtet werden.
quelle
Nee. Wenn Sie MyISAM-Tabellen verwenden, führen sie meines Wissens nur Tabellensperren durch - es gibt keine Datensatzsperren, sie versuchen lediglich, alles durch Einfachheit hyperfast zu halten. (Andere MySQL-Tabellen funktionieren anders.) In jedem Fall können Sie die Tabelle in eine andere Tabelle kopieren, ändern und dann wechseln, um sie auf Unterschiede zu aktualisieren.
Dies ist eine so massive Änderung, dass ich bezweifle, dass ein DBMS sie unterstützen würde. Es wird als Vorteil angesehen, dies überhaupt mit Daten in der Tabelle tun zu können.
quelle
Vorübergehende Lösung...
Eine andere Lösung könnte darin bestehen, eine weitere Tabelle mit dem Primärschlüssel der ursprünglichen Tabelle zusammen mit Ihrer neuen Spalte hinzuzufügen.
Füllen Sie Ihren Primärschlüssel in die neue Tabelle ein und füllen Sie die Werte für die neue Spalte in Ihrer neuen Tabelle aus. Ändern Sie Ihre Abfrage, um diese Tabelle für ausgewählte Vorgänge zu verbinden. Außerdem müssen Sie diesen Spaltenwert separat einfügen und aktualisieren.
Wenn Sie Ausfallzeiten haben, können Sie die ursprüngliche Tabelle ändern, Ihre DML-Abfragen ändern und Ihre zuvor erstellte neue Tabelle löschen
Andernfalls können Sie sich für die Clustering-Methode, die Replikation und das pt-online-Schema-Tool von percona entscheiden
quelle
Mit dem Innodb-Plugin können ALTER TABLE-Anweisungen, die nur Sekundärindizes hinzufügen oder löschen, "schnell" ausgeführt werden, dh ohne die Tabelle neu zu erstellen.
Im Allgemeinen umfasst jedoch in MySQL jede ALTER TABLE das Neuerstellen der gesamten Tabelle, was sehr lange dauern kann (dh wenn die Tabelle eine nützliche Datenmenge enthält).
Sie müssen Ihre Anwendung wirklich so gestalten, dass ALTER TABLE-Anweisungen nicht regelmäßig ausgeführt werden müssen. Sie möchten sicher nicht, dass ALTER TABLE während des normalen Ausführens der Anwendung ausgeführt wird, es sei denn, Sie sind bereit zu warten oder ändern winzige Tabellen.
quelle
Ich würde einen von zwei Ansätzen empfehlen:
Entwerfen Sie Ihre Datenbanktabellen unter Berücksichtigung möglicher Änderungen. Ich habe zum Beispiel mit Content Management Systemen gearbeitet, die Datenfelder in Inhalten regelmäßig ändern. Anstatt die physische Datenbankstruktur so zu erstellen, dass sie den anfänglichen CMS-Feldanforderungen entspricht, ist es viel besser, eine flexible Struktur zu erstellen. In diesem Fall verwenden Sie ein Blob-Textfeld (z. B. varchar (max)), um flexible XML-Daten zu speichern. Dies macht strukturelle Veränderungen sehr seltener. Strukturelle Änderungen können kostspielig sein, daher sind auch hier Kostenvorteile zu verzeichnen.
Systemwartungszeit haben. Entweder wird das System während Änderungen (monatlich usw.) offline geschaltet, und die Änderungen werden während der am wenigsten frequentierten Tageszeit (z. B. 3 bis 5 Uhr morgens) geplant. Die Änderungen werden vor dem Produktions-Rollout bereitgestellt, sodass Sie eine gute feste Fensterschätzung der Ausfallzeiten haben.
2a. Haben Sie redundante Server, damit bei Ausfallzeiten des Systems nicht der gesamte Standort ausfällt. Auf diese Weise können Sie Ihre Updates gestaffelt "rollen", ohne die gesamte Website herunterzufahren.
Die Optionen 2 und 2a sind möglicherweise nicht durchführbar. Sie sind in der Regel nur für größere Standorte / Betriebe vorgesehen. Dies sind jedoch gültige Optionen, und ich habe alle hier vorgestellten Optionen persönlich verwendet.
quelle
Wenn jemand dies noch liest oder zufällig hierher kommt, ist dies der große Vorteil der Verwendung eines NoSQL-Datenbanksystems wie Mongodb. Ich hatte das gleiche Problem beim Ändern der Tabelle, um entweder Spalten für zusätzliche Funktionen oder Indizes für eine große Tabelle mit Millionen von Zeilen und hohen Schreibvorgängen hinzuzufügen. Es würde für eine sehr lange Zeit sperren, so dass dies in der LIVE-Datenbank unsere Benutzer frustrieren würde. Auf kleinen Tischen kann man damit durchkommen.
Ich hasse die Tatsache, dass wir "unsere Tabellen entwerfen müssen, um sie nicht zu verändern". Ich glaube einfach nicht, dass das in der heutigen Website-Welt funktioniert. Sie können nicht vorhersagen, wie Benutzer Ihre Software verwenden werden. Deshalb ändern Sie die Dinge schnell, basierend auf dem Feedback der Benutzer. Mit mongodb können Sie nach Belieben "Spalten" ohne Ausfallzeiten hinzufügen. Sie fügen sie nicht einmal wirklich hinzu, sondern fügen nur Daten mit neuen Spalten ein und dies geschieht automatisch.
Ein Besuch lohnt sich: www.mongodb.com
quelle
Im Allgemeinen lautet die Antwort "Nein". Sie ändern die Struktur der Tabelle, für die möglicherweise viele Aktualisierungen erforderlich sind ", und ich stimme dem definitiv zu. Wenn Sie dies voraussichtlich häufig tun, biete ich eine Alternative zu" Dummy "-Spalten an - verwenden Sie
VIEW
stattdessen s von Tabellen für einSELECT
relativ geringes Gewicht und die Indirektheit durch einen Blick Daten ing. IIRC, ist die Definition einer Ansicht zu ändern erfolgt, wenn der Abfrageplan kompiliert wird. der Aufwand ist , dass Sie die Spalte in eine neue Tabelle müsste hinzufügen und machen das AnsichtJOIN
in der Spalte.Dies funktioniert natürlich nur, wenn Sie Fremdschlüssel verwenden können, um Kaskaden von Löschvorgängen und so weiter durchzuführen. Der andere Vorteil ist, dass Sie eine neue Tabelle erstellen können, die eine Kombination der Daten enthält, und die Ansicht darauf verweisen können, ohne die Client-Nutzung zu stören.
Nur ein Gedanke.
quelle
Der Unterschied zwischen Postgres und MySQL besteht in dieser Hinsicht darin, dass in Postgres keine Tabelle neu erstellt wird, sondern das Datenwörterbuch geändert wird, das Oracle ähnelt. Daher ist der Vorgang schnell, während immer noch eine exklusive DDL-Tabellensperre für sehr kurze Zeit zugewiesen werden muss, wie oben von anderen angegeben.
In MySQL kopiert der Vorgang Daten in eine neue Tabelle, während Transaktionen blockiert werden, was für MySQL-Datenbankadministratoren vor Version 5.6 von größter Bedeutung war.
Die gute Nachricht ist, dass seit der Veröffentlichung von MySQL 5.6 die Einschränkung größtenteils aufgehoben wurde und Sie jetzt die wahre Leistung der MYSQL-Datenbank genießen können.
quelle
Wie SeanDowney erwähnt hat,
pt-online-schema-change
ist es eines der besten Werkzeuge, um das zu tun, was Sie in der Frage hier beschrieben haben. Ich habe kürzlich viele Schemaänderungen an einer Live-Datenbank vorgenommen und es lief ziemlich gut. Sie können mehr darüber in meinem Blog-Beitrag hier lesen: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/ .quelle
Sie sollten es auf jeden Fall versuchen
pt-online-schema-change
. Ich habe dieses Tool verwendet, um Migrationen auf AWS RDS mit mehreren Slaves durchzuführen, und es hat für mich sehr gut funktioniert. Ich habe einen ausführlichen Blog-Beitrag darüber geschrieben, wie man das macht, was für Sie hilfreich sein könnte.Blog: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/
quelle
Dummy-Spalten sind eine gute Idee, wenn Sie ihren Typ vorhersagen können (und sie auf Null setzen können). Überprüfen Sie, wie Ihre Speicher-Engine mit Nullen umgeht.
MyISAM sperrt alles, wenn Sie am Flughafen am Telefon nebenbei einen Tabellennamen erwähnen. Das macht es einfach ...
Davon abgesehen sind Schlösser keine so große Sache. Solange Sie nicht versuchen, jeder Zeile einen Standardwert für die neue Spalte hinzuzufügen, sondern diesen als Null festlegen, und Ihre Speicher-Engine intelligent genug ist, um ihn nicht zu schreiben, sollten Sie mit einer einzigen Sperre einverstanden sein lange genug gehalten, um die Metadaten zu aktualisieren. Wenn Sie versuchen, einen neuen Wert zu schreiben, sind Sie Toast.
quelle
TokuDB kann Spalten hinzufügen / löschen und Indizes "hot" hinzufügen. Die Tabelle ist während des gesamten Prozesses vollständig verfügbar. Es ist über www.tokutek.com erhältlich
quelle
Nicht wirklich.
Schließlich ändern Sie die zugrunde liegende Struktur der Tabelle, und das sind einige Informationen, die für das zugrunde liegende System sehr wichtig sind. Sie verschieben (wahrscheinlich) auch einen Großteil der Daten auf der Festplatte.
Wenn Sie dies häufig tun möchten, sollten Sie die Tabelle einfach mit "Dummy" -Spalten auffüllen, die für die zukünftige Verwendung verfügbar sind.
quelle