Cóż ... Huh. Od lat nikt nie wspomniał o jednej subtelnej rzeczy.
Mimo, DROP TABLE IF EXISTS `bla`; CREATE TABLE `bla` ( ... );że wydaje się to rozsądne, prowadzi to do sytuacji, w której stary stół już nie istnieje, a nowy nie został jeszcze utworzony: jakiś klient może w tym momencie próbować uzyskać dostęp do tabeli tematów.
Lepszym sposobem jest utworzenie zupełnie nowej tabeli i zamiana jej na starą (zawartość tabeli jest tracona):
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`;
- Powinieneś sprawdzić wynik
CREATE ...i nie kontynuować w przypadku błędu , ponieważ awaria oznacza, że inny wątek nie zakończył tego samego skryptu: albo zawiesił się w środku, albo po prostu jeszcze się nie skończył - dobrze sprawdź rzeczy samodzielnie.
- Następnie należy najpierw sprawdzić wynik
RENAME ...i nie kontynuować w przypadku sukcesu : cała operacja została zakończona pomyślnie; Co więcej, uruchomienie następnego RENAME ...może (i będzie) niebezpieczne, jeśli inny wątek już rozpoczął tę samą sekwencję (lepiej omówić ten przypadek niż nie, patrz uwaga na temat blokowania poniżej).
- Druga
RENAME ...niepodzielnie zastępuje definicję tabeli, szczegółowe informacje można znaleźć w
podręczniku MySQL
.
- W końcu
DROP ...oczywiście po prostu sprząta stary stół.
Zawijanie wszystkich instrukcji czymś takim jak SELECT GET_LOCK('__upgrade', -1); ... DO RELEASE_LOCK('__upgrade');pozwala po prostu wywoływać wszystkie instrukcje sekwencyjnie bez sprawdzania błędów, ale nie sądzę, aby to był dobry pomysł: zwiększa się złożoność i funkcje blokujące w MySQL nie są bezpieczne dla replikacji opartej na instrukcjach.
Jeśli dane tabeli powinny przetrwać aktualizację definicji tabeli ... W ogólnym przypadku jest to znacznie bardziej złożona historia o porównywaniu definicji tabel w celu znalezienia różnic i stworzenia odpowiedniego ALTER ...zestawienia, co nie zawsze jest możliwe automatycznie, np. Przy zmianie nazw kolumn.
Uwaga dodatkowa 1:
Możesz radzić sobie z widokami, używając tego samego podejścia, w tym przypadku CREATE/DROP TABLEpo prostu przekształca się w CREATE/DROP VIEWpodczas gdy RENAME TABLEpozostaje niezmieniony. W rzeczywistości możesz nawet zmienić tabelę w widok i odwrotnie.
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`;
Uwaga dodatkowa 2:
użytkownicy MariaDB powinni być zadowoleni CREATE OR REPLACE TABLE/VIEW, która już dba o problem tematyczny i to jest dobre punkty.