Nun ... Huh. Jahrelang erwähnte niemand eine subtile Sache.
Obwohl dies DROP TABLE IF EXISTS `bla`; CREATE TABLE `bla` ( ... );
vernünftig erscheint, führt dies zu einer Situation, in der die alte Tabelle bereits verschwunden ist und noch keine neue erstellt wurde: Einige Clients versuchen möglicherweise gerade, auf die betreffende Tabelle zuzugreifen.
Der bessere Weg ist, eine brandneue Tabelle zu erstellen und diese gegen eine alte auszutauschen (der Inhalt der Tabelle geht verloren):
CREATE TABLE `bla__new` (id int); /* if not ok: terminate, report error */
RENAME TABLE `bla__new` to `bla`; /* if ok: terminate, report success */
RENAME TABLE `bla` to `bla__old`, `bla__new` to `bla`;
DROP TABLE IF EXISTS `bla__old`;
- Sie sollten das Ergebnis von überprüfen
CREATE ...
und im Fehlerfall nicht fortfahren , da ein Fehler bedeutet, dass ein anderer Thread nicht dasselbe Skript beendet hat: entweder weil er in der Mitte abgestürzt ist oder nur noch nicht beendet wurde - das ist eine gute Idee Inspizieren Sie die Dinge selbst.
- Dann sollten Sie das Ergebnis von first überprüfen
RENAME ...
und im Erfolgsfall nicht fortfahren : Der gesamte Vorgang ist erfolgreich abgeschlossen; Darüber hinaus RENAME ...
kann (und wird) das Ausführen von next unsicher sein, wenn ein anderer Thread bereits dieselbe Sequenz gestartet hat (es ist besser, diesen Fall abzudecken, als ihn nicht abzudecken, siehe Sperrhinweis unten).
- Zweitens
RENAME ...
ersetzt atomar die Tabellendefinition. Weitere
Informationen finden Sie im MySQL-Handbuch .
- Endlich
DROP ...
räumt natürlich nur der alte Tisch auf.
Das Umschließen aller Anweisungen mit so etwas wie SELECT GET_LOCK('__upgrade', -1); ... DO RELEASE_LOCK('__upgrade');
ermöglicht es, alle Anweisungen nacheinander ohne Fehlerprüfung aufzurufen, aber ich halte dies nicht für eine gute Idee: Die Komplexität steigt und Sperrfunktionen in MySQL sind für die anweisungsbasierte Replikation nicht sicher.
Wenn die Tabellendaten das Upgrade der Tabellendefinition überleben sollen ... Im Allgemeinen ist es weitaus komplexer, Tabellendefinitionen zu vergleichen, um Unterschiede herauszufinden und die richtige ALTER ...
Anweisung zu erstellen , was nicht immer automatisch möglich ist, z. B. wenn Spalten umbenannt werden.
Randnotiz 1:
Sie können Ansichten mit demselben Ansatz behandeln. In diesem Fall werden CREATE/DROP TABLE
nur Transformationen in CREATE/DROP VIEW
while geändert, während sie RENAME TABLE
unverändert bleiben. Sie können sogar den Tisch in eine Ansicht verwandeln und umgekehrt.
CREATE VIEW `foo__new` as ...; /* if not ok: terminate, report error */
RENAME TABLE `foo__new` to `foo`; /* if ok: terminate, report success */
RENAME TABLE `foo` to `foo__old`, `foo__new` to `foo`;
DROP VIEW IF EXISTS `foo__old`;
Randnotiz 2:
MariaDB-Benutzer sollten zufrieden sein CREATE OR REPLACE TABLE/VIEW
, was sich bereits um das Thema und die Feinheiten kümmert.