Eh bien ... Huh. Pendant des années, personne n'a mentionné une chose subtile.
Bien que cela DROP TABLE IF EXISTS `bla`; CREATE TABLE `bla` ( ... );
semble raisonnable, cela conduit à une situation où l'ancienne table est déjà partie et qu'une nouvelle n'a pas encore été créée: certains clients peuvent essayer d'accéder à la table des sujets à ce moment.
Le meilleur moyen est de créer une nouvelle table et de la remplacer par une ancienne (le contenu de la table est perdu):
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`;
- Vous devriez vérifier le résultat de
CREATE ...
et ne pas continuer en cas d'erreur , car un échec signifie qu'un autre thread n'a pas terminé le même script: soit parce qu'il s'est écrasé au milieu, soit parce qu'il n'a pas encore fini - c'est une bonne idée de inspectez les choses par vous-même.
- Ensuite, vous devez d'abord vérifier le résultat
RENAME ...
et ne pas continuer en cas de succès : toute l'opération est terminée avec succès; encore plus, l'exécution suivante RENAME ...
peut (et sera) dangereuse si un autre thread a déjà commencé la même séquence (il vaut mieux couvrir ce cas que de ne pas couvrir, voir la note de verrouillage ci-dessous).
- La seconde
RENAME ...
remplace atomiquement la définition de table, reportez-vous au
manuel MySQL
pour plus de détails.
- Enfin,
DROP ...
nettoie simplement l'ancienne table, évidemment.
Emballer toutes les instructions avec quelque chose comme SELECT GET_LOCK('__upgrade', -1); ... DO RELEASE_LOCK('__upgrade');
permet d'appeler toutes les instructions de manière séquentielle sans vérification d'erreur, mais je ne pense pas que ce soit une bonne idée: la complexité augmente et les fonctions de verrouillage dans MySQL ne sont pas sûres pour la réplication basée sur des instructions.
Si les données de table doivent survivre à la mise à niveau de la définition de table ... Pour le cas général, il est beaucoup plus complexe de comparer les définitions de table pour découvrir les différences et produire une ALTER ...
déclaration appropriée , ce qui n'est pas toujours possible automatiquement, par exemple lorsque les colonnes sont renommées.
Note latérale 1:
Vous pouvez traiter les vues en utilisant la même approche, dans ce cas CREATE/DROP TABLE
se transforme simplement en tant CREATE/DROP VIEW
que RENAME TABLE
reste inchangé. En fait, vous pouvez même transformer la table en vue et vice versa.
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`;
Note latérale 2: les
utilisateurs de MariaDB devraient être satisfaits CREATE OR REPLACE TABLE/VIEW
, qui se soucient déjà du problème du sujet et de ses bons points.