Bueno ... eh. Durante años, nadie mencionó una cosa sutil.
A pesar de que DROP TABLE IF EXISTS `bla`; CREATE TABLE `bla` ( ... );
parece razonable, lleva a una situación en la que la tabla anterior ya no existe y la nueva aún no se ha creado: algunos clientes pueden intentar acceder a la tabla de temas en este momento.
La mejor manera es crear una tabla nueva e intercambiarla por una antigua (se pierde el contenido de la tabla):
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`;
- Debe verificar el resultado
CREATE ...
y no continuar en caso de error , porque el error significa que otro hilo no terminó el mismo script: ya sea porque se bloqueó en el medio o simplemente no terminó aún; es una buena idea inspeccionar las cosas por ti mismo.
- Luego, primero debe verificar el resultado
RENAME ...
y no continuar en caso de éxito : toda la operación se ha completado con éxito; aún más, ejecutar el siguiente RENAME ...
puede (y será) inseguro si otro hilo ya ha comenzado la misma secuencia (es mejor cubrir este caso que no cubrirlo, vea la nota de bloqueo a continuación).
- El segundo
RENAME ...
reemplaza atómicamente la definición de la tabla; consulte el
manual de MySQL
para obtener más detalles.
- Por fin,
DROP ...
simplemente limpia la vieja mesa, obviamente.
Ajustar todas las declaraciones con algo como esto SELECT GET_LOCK('__upgrade', -1); ... DO RELEASE_LOCK('__upgrade');
permite invocar todas las declaraciones secuencialmente sin verificación de errores, pero no creo que sea una buena idea: la complejidad aumenta y las funciones de bloqueo en MySQL no son seguras para la replicación basada en declaraciones.
Si los datos de la tabla deben sobrevivir a la actualización de la definición de la tabla ... Para el caso general, es una historia mucho más compleja sobre la comparación de las definiciones de la tabla para descubrir diferencias y producir una ALTER ...
declaración adecuada , que no siempre es posible automáticamente, por ejemplo, cuando se cambian los nombres de las columnas.
Nota al margen 1:
puede manejar vistas utilizando el mismo enfoque, en este caso CREATE/DROP TABLE
simplemente se transforma en CREATE/DROP VIEW
mientras RENAME TABLE
permanece sin cambios. De hecho, incluso puede convertir la tabla a la vista y viceversa.
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`;
Nota al
margen 2: los usuarios de MariaDB deberían estar contentos con CREATE OR REPLACE TABLE/VIEW
eso, que ya se preocupa por el problema del tema y sus puntos finos.