Podczas wykonywania instrukcji ALTER TABLE w MySQL cała tabela jest blokowana do odczytu (zezwala na równoczesne odczyty, ale zabrania współbieżnych zapisów) na czas trwania instrukcji. Jeśli jest to duża tabela, instrukcje INSERT lub UPDATE mogą zostać zablokowane na dłuuuugi czas. Czy istnieje sposób na wykonanie „gorącej zmiany”, na przykład dodanie kolumny w taki sposób, aby tabela była nadal aktualizowana w trakcie całego procesu?
Przede wszystkim jestem zainteresowany rozwiązaniem dla MySQL, ale byłbym zainteresowany innymi RDBMS, jeśli MySQL nie może tego zrobić.
Aby wyjaśnić, moim celem jest po prostu uniknięcie przestojów, gdy nowa funkcja, która wymaga dodatkowej kolumny tabeli, jest wypychana do produkcji. Każdy schemat bazy danych będzie się z czasem zmieniać, to po prostu fakt. Nie widzę powodu, dla którego mielibyśmy zaakceptować fakt, że te zmiany muszą nieuchronnie skutkować przestojami; to jest po prostu słabe.
źródło
Odpowiedzi:
Jedyną inną opcją jest zrobienie ręcznie tego, co i tak robi wiele systemów RDBMS ...
- Utwórz nową tabelę
Następnie możesz skopiować zawartość starej tabeli na porcję naraz. Zawsze zachowując ostrożność w przypadku jakichkolwiek INSERT / UPDATE / DELETE w tabeli źródłowej. (Może być zarządzany przez wyzwalacz. Chociaż spowodowałoby to spowolnienie, nie jest to blokada ...)
Po zakończeniu zmień nazwę tabeli źródłowej, a następnie zmień nazwę nowej tabeli. Najlepiej w transakcji.
Po zakończeniu ponownie skompiluj wszystkie procedury składowane itp., Które używają tej tabeli. Plany wykonania prawdopodobnie stracą ważność.
EDYTOWAĆ:
Pojawiły się pewne komentarze, że to ograniczenie jest nieco słabe. Pomyślałem więc, że spojrzę na to z nowej perspektywy, aby pokazać, dlaczego tak jest ...
źródło
Percona tworzy narzędzie zwane pt-online-schema-change, które to umożliwia.
Zasadniczo tworzy kopię tabeli i modyfikuje nową tabelę. Aby zachować synchronizację nowej tabeli z oryginalną, do aktualizacji używa wyzwalaczy. Umożliwia to dostęp do oryginalnej tabeli, podczas gdy nowa tabela jest przygotowywana w tle.
Jest to podobne do sugerowanej powyżej metody Demsa, ale odbywa się to w sposób zautomatyzowany.
Niektóre z ich narzędzi mają krzywą uczenia się, a mianowicie łączenie się z bazą danych, ale kiedy już to zrobisz, są świetnymi narzędziami.
Dawny:
źródło
To pytanie z 2009 roku. Teraz MySQL oferuje rozwiązanie:
Online DDL (język definicji danych)
Pozwala dostosować równowagę między wydajnością a współbieżnością podczas operacji DDL, wybierając, czy całkowicie blokować dostęp do tabeli (klauzula LOCK = EXCLUSIVE), zezwalać na zapytania, ale nie na DML (LOCK = klauzula SHARED) lub zezwalać na pełne zapytania i DML dostęp do tabeli (klauzula LOCK = NONE). W przypadku pominięcia klauzuli LOCK lub określenia LOCK = DEFAULT MySQL zezwala na możliwie największą współbieżność w zależności od typu operacji.
Wykonywanie zmian na miejscu, jeśli to możliwe, zamiast tworzenia nowej kopii tabeli, pozwala uniknąć tymczasowego wzrostu wykorzystania miejsca na dysku i obciążenia we / wy związanego z kopiowaniem tabeli i rekonstrukcją indeksów pomocniczych.
zobacz Podręcznik MySQL 5.6 -> InnoDB i Online DDL, aby uzyskać więcej informacji.
Wygląda na to, że DDL online jest również dostępny w MariaDB
MariaDB KB o ALTER TABLE
źródło
Zobacz internetowe narzędzie zmiany schematu Facebooka.
http://www.facebook.com/notes/mysql-at-facebook/online-schema-change-for-mysql/430801045932
Nie dla słabego serca; ale spełni swoje zadanie.
źródło
Polecam Postgres, jeśli jest taka opcja. W przypadku postgres zasadniczo nie ma przestojów przy następujących procedurach:
Inną wspaniałą cechą jest to, że większość instrukcji DDL to transakcje transakcyjne, więc możesz wykonać całą migrację w ramach transakcji SQL, a jeśli coś pójdzie nie tak, wszystko zostanie wycofane.
Napisałem to trochę temu, być może może to rzucić nieco więcej wglądu w inne zalety.
źródło
Ponieważ pytałeś o inne bazy danych, oto kilka informacji o Oracle.
Dodanie kolumny NULL do tabeli Oracle jest bardzo szybką operacją, ponieważ aktualizuje tylko słownik danych. To utrzymuje wyłączną blokadę na stole przez bardzo krótki czas. Spowoduje to jednak unieważnienie wszelkich zależnych procedur składowanych, widoków, wyzwalaczy itp. Zostaną one ponownie skompilowane automatycznie.
Stamtąd, jeśli to konieczne, możesz utworzyć indeks za pomocą klauzuli ONLINE. Ponownie, tylko bardzo krótkie blokady słownika danych. Odczyta całą tabelę, szukając rzeczy do zindeksowania, ale nikogo nie blokuje podczas wykonywania tej czynności.
Jeśli potrzebujesz dodać klucz obcy, możesz to zrobić i sprawić, by Oracle zaufało Ci, że dane są poprawne. W przeciwnym razie musi odczytać całą tabelę i zweryfikować wszystkie wartości, które mogą być powolne (najpierw utwórz indeks).
Jeśli chcesz umieścić wartość domyślną lub obliczoną w każdym wierszu nowej kolumny, musisz uruchomić masową aktualizację lub może mały program narzędziowy, który zapełni nowe dane. Może to być powolne, zwłaszcza jeśli rzędy stają się znacznie większe i nie mieszczą się już w swoich blokach. Podczas tego procesu można zarządzać blokowaniem. Ponieważ stara wersja Twojej aplikacji, która nadal działa, nie zawiera informacji o tej kolumnie, możesz potrzebować podstępnego wyzwalacza lub określić domyślną.
Stamtąd możesz wykonać przełączenie na serwerach aplikacji do nowej wersji kodu i będzie on nadal działać. Opuść podstępny spust.
Alternatywnie możesz użyć DBMS_REDEFINITION, która jest czarną skrzynką zaprojektowaną do tego typu rzeczy.
Wszystko to jest tak trudne do przetestowania, itp., Że mamy po prostu wczesną, niedzielną przerwę w pracy, ilekroć wydajemy wersję główną.
źródło
Jeśli nie możesz pozwolić sobie na przestoje dla bazy danych podczas wykonywania aktualizacji aplikacji, powinieneś rozważyć utrzymanie klastra z dwoma węzłami w celu zapewnienia wysokiej dostępności. Dzięki prostej konfiguracji replikacji można by dokonać prawie w całości zmian strukturalnych online, takich jak ta, którą sugerujesz:
Nie zawsze jest to łatwe, ale działa, zazwyczaj bez przestojów! Drugi węzeł nie musi być tylko pasywny, może służyć do testowania, tworzenia statystyk lub jako węzeł rezerwowy. Jeśli nie masz infrastruktury, replikację można skonfigurować w ramach jednego komputera (z dwoma wystąpieniami MySQL).
źródło
Nie. Jeśli korzystasz z tabel MyISAM, zgodnie z moim najlepszym zrozumieniem, robią one tylko blokady tabel - nie ma blokad rekordów, po prostu starają się zachować wszystko błyskawicznie dzięki prostocie. (Inne tabele MySQL działają inaczej). W każdym przypadku możesz skopiować tabelę do innej tabeli, zmienić ją, a następnie przełączyć, aktualizując ze względu na różnice.
Jest to tak ogromna zmiana, że wątpię, by jakikolwiek DBMS ją wspierał. Możliwość zrobienia tego z danymi w tabeli jest uważana za korzyść w pierwszej kolejności.
źródło
Rozwiązanie tymczasowe ...
Innym rozwiązaniem może być dodanie kolejnej tabeli z kluczem podstawowym oryginalnej tabeli wraz z nową kolumną.
Wypełnij swój klucz podstawowy w nowej tabeli i wypełnij wartości dla nowej kolumny w nowej tabeli i zmodyfikuj zapytanie, aby dołączyć do tej tabeli dla operacji wybierania, a także musisz wstawić, zaktualizować oddzielnie dla tej wartości kolumny.
Gdy możesz uzyskać przestój, możesz zmienić oryginalną tabelę, zmodyfikować zapytania DML i porzucić nową, utworzoną wcześniej tabelę
W przeciwnym razie możesz skorzystać z metody klastrowania, replikacji, narzędzia pt-online-schema firmy Percona
źródło
Korzystając z wtyczki Innodb, instrukcje ALTER TABLE, które tylko dodają lub usuwają indeksy pomocnicze, mogą być wykonywane „szybko”, tj. Bez przebudowywania tabeli.
Jednak ogólnie rzecz biorąc, w MySQL każda ALTER TABLE wymaga przebudowania całej tabeli, co może zająć bardzo dużo czasu (tj. Jeśli tabela zawiera użyteczną ilość danych).
Naprawdę musisz zaprojektować swoją aplikację tak, aby instrukcje ALTER TABLE nie musiały być wykonywane regularnie; na pewno nie chcesz, aby ALTER TABLE była wykonywana podczas normalnego działania aplikacji, chyba że jesteś przygotowany na czekanie lub zmieniasz małe tabele.
źródło
Poleciłbym jedno z dwóch podejść:
Projektuj tabele bazy danych z uwzględnieniem potencjalnych zmian. Na przykład pracowałem z systemami zarządzania treścią, które regularnie zmieniają pola danych w treści. Zamiast budować fizyczną strukturę bazy danych w celu dopasowania do początkowych wymagań pola CMS, znacznie lepiej jest zbudować elastyczną strukturę. W tym przypadku użycie pola tekstowego typu blob (na przykład varchar (max)) do przechowywania elastycznych danych XML. To sprawia, że zmiany strukturalne są bardzo rzadsze. Zmiany strukturalne mogą być kosztowne, więc koszty również są korzystne.
Miej czas na konserwację systemu. System przechodzi w tryb offline podczas zmian (co miesiąc itp.), A zmiany są planowane w czasie o najmniej intensywnym ruchu w ciągu dnia (na przykład 3-5 rano). Zmiany są wprowadzane etapowo przed wdrożeniem produkcyjnym, więc będziesz mieć dobre oszacowanie czasu przestoju w oknie.
2a. Posiadaj redundantne serwery, dzięki czemu podczas przestoju systemu cała witryna nie ulegnie awarii. Umożliwiłoby to „udostępnianie” aktualizacji w sposób rozłożony w czasie, bez wyłączania całej witryny.
Warianty 2 i 2a mogą być niewykonalne; zwykle dotyczą tylko większych witryn / operacji. Są to jednak ważne opcje i osobiście korzystałem ze wszystkich przedstawionych tutaj opcji.
źródło
Jeśli ktoś nadal to czyta lub przychodzi tutaj, jest to duża zaleta korzystania z systemu baz danych NoSQL, takiego jak mongodb. Miałem ten sam problem, jeśli chodzi o zmianę tabeli, aby dodać kolumny dla dodatkowych funkcji lub indeksy w dużej tabeli z milionami wierszy i wysokimi zapisami. W rezultacie blokowałby się na bardzo długi czas, więc zrobienie tego w bazie danych LIVE frustrowałoby naszych użytkowników. Na małych stolikach możesz uciec.
Nienawidzę faktu, że musimy „projektować nasze tabele, aby ich nie zmieniać”. Po prostu nie sądzę, żeby to działało w dzisiejszym świecie witryn internetowych. Nie możesz przewidzieć, jak ludzie będą używać twojego oprogramowania, dlatego szybko zmieniasz rzeczy na podstawie opinii użytkowników. Dzięki mongodb możesz dowolnie dodawać „kolumny” bez przestojów. Tak naprawdę nawet ich nie dodajesz, po prostu wstawiasz dane z nowymi kolumnami i robi to automatycznie.
Warto sprawdzić: www.mongodb.com
źródło
Ogólnie rzecz biorąc, odpowiedź brzmi „nie”. Zmieniasz strukturę tabeli, która potencjalnie będzie wymagała wielu aktualizacji. ”I zdecydowanie się z tym zgadzam. Jeśli spodziewasz się, że będziesz to robić często, zaoferuję alternatywę dla„ pustych ”kolumn -
VIEW
zamiast tego użyj s tabel dlaSELECT
danych. IIRC, zmiana definicji widoku jest stosunkowo niewielka, a pośrednia zmiana widoku jest wykonywana podczas kompilacji planu kwerend. Koszt jest taki, że trzeba by dodać kolumnę do nowej tabeli i zobaczJOIN
w kolumnie.Oczywiście działa to tylko wtedy, gdy można używać kluczy obcych do wykonywania kaskadowego usuwania i tak dalej. Drugą zaletą jest to, że możesz utworzyć nową tabelę zawierającą kombinację danych i skierować do niej widok bez zakłócania użytkowania klienta.
Tylko myśl.
źródło
Różnica między Postgresem a MySQL w tym zakresie polega na tym, że w Postgres nie odtwarza tabeli, ale modyfikuje słownik danych, który jest podobny do Oracle. Dlatego operacja jest szybka, podczas gdy nadal wymaga przydzielenia wyłącznej blokady tabeli DDL na bardzo krótki czas, jak stwierdzono powyżej przez innych.
W MySQL operacja skopiuje dane do nowej tabeli podczas blokowania transakcji, co było głównym problemem dla baz danych MySQL przed wersją 5.6.
Dobra wiadomość jest taka, że od czasu wydania MySQL 5.6 ograniczenie zostało w większości zniesione i teraz możesz cieszyć się prawdziwą mocą bazy danych MYSQL.
źródło
Jak wspomniał SeanDowney,
pt-online-schema-change
jest to jedno z najlepszych narzędzi do zrobienia tego, co opisałeś w pytaniu tutaj. Niedawno dokonałem wielu zmian schematu w działającej bazie danych i poszło całkiem nieźle. Możesz przeczytać więcej na ten temat na moim blogu tutaj: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/ .źródło
Zdecydowanie powinieneś spróbować
pt-online-schema-change
. Używałem tego narzędzia do migracji na AWS RDS z wieloma niewolnikami i działa bardzo dobrze. Napisałem obszerny wpis na blogu o tym, jak zrobić to, co może być dla Ciebie pomocne.Blog: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/
źródło
Kolumny atrapy są dobrym pomysłem, jeśli potrafisz przewidzieć ich typ (i uczynić je zerowymi). Sprawdź, jak Twój aparat pamięci obsługuje wartości zerowe.
MyISAM zablokuje wszystko, jeśli choćby wymienisz nazwę stolika podczas rozmowy telefonicznej na lotnisku. Po prostu to robi ...
Biorąc to pod uwagę, zamki nie są naprawdę takie duże; tak długo, jak nie próbujesz dodać domyślnej wartości dla nowej kolumny do każdego wiersza, ale pozostawisz ją jako zerową, a twój silnik magazynu jest wystarczająco inteligentny, aby go nie pisać, powinieneś być w porządku z blokadą, która jest tylko trzymany wystarczająco długo, aby zaktualizować metadane. Jeśli spróbujesz wpisać nową wartość, cóż, jesteś uniesiony.
źródło
TokuDB może dodawać / usuwać kolumny i dodawać indeksy „na gorąco”, tabela jest w pełni dostępna przez cały proces. Jest dostępny na www.tokutek.com
źródło
Nie całkiem.
W końcu ZMIENISZ podstawową strukturę tabeli, a to jest trochę informacji, które są dość ważne dla podstawowego systemu. Przenosisz również (prawdopodobnie) większość danych na dysku.
Jeśli planujesz robić to często, lepiej po prostu uzupełnij tabelę „fikcyjnymi” kolumnami, które będą dostępne do wykorzystania w przyszłości.
źródło