2009-08-20 10 views
9

Mamy tabelę (obecnie InnoDB), która zawiera około 500 000 wierszy. Jest to kolejka zadań do uruchomienia. Jest przechowywany w bazie danych MySQL.Zakleszczenia w MySQL usuwające wiersze

W sposób ciągły, co najmniej raz na sekundę, ale czasami częściej wybieramy z niej dane, a następnie aktualizujemy niektóre wiersze. Raz dziennie wycinamy stare rzędy ze stołu.

Zaczęliśmy dostawać zakleszczenia na stół, co spowodowało wstrzymanie naszego przetwarzania zadań. Te zakleszczenia powstały podczas nocnego prune. Połączenie DELETE, SELECT i UPDATE oznaczało, że w zasadzie nic nie może się wydarzyć. Niestety nie mam danych wyjściowych SHOW ENGINE INNODB STATUS.

Chciałbym poznać najlepszą opcję radzenia sobie z tym. Pamiętaj, że nasz kod wykrywa zakleszczenia i ponownie wysyła zapytanie. Poza tym, dawno temu odkryliśmy, że usuwanie wszystkich pasujących wierszy naraz było zbyt dużym obciążeniem dla tabeli bazy danych, która odnotowała dużą aktywność, więc LIMIT usuniemy nasze usunięcia do 10 000 wierszy naraz i kontynuujemy ponowne wysyłanie zapytania do momentu, aż wszystkie niezbędne wiersze zostaną usunięte. przycięte.

widzę następujące opcje i chciałby opinie na którym są najlepsze, czy sugestie dotyczące innych opcji:

  1. DELETE mniej wierszy naraz
  2. Zastosowanie wykładniczy ograniczania mocy na naszych usuwa, choć obawiam się, że to nie pomoże, biorąc pod uwagę nasz specyficzny nakład pracy
  3. TABLICE ZABLOKOWANIA zgodnie z MySQL documentation. Prawdopodobnie moglibyśmy zaakceptować blokowanie instrukcji SELECT i UPDATE na czas usuwania.
  4. Przełącz na typ tabeli MyISAM. Udaliśmy się z InnoDB, ponieważ początkowo używaliśmy transakcji na tej tabeli. Tak już nie jest. Nie jestem wystarczająco zaznajomiony ze specyfiką, aby wiedzieć, czy jest to opłacalne rozwiązanie.
  5. Być może użyj UPDATE LOW_PRIORITY. Może być tak, że DELETE nie wpływają na SELECT, tylko UPDATE, i to może być wystarczające.
+1

Wszystkie napotkane przeze mnie zakleszczenia zostały spowodowane niezakończonymi transakcjami. Upewnij się, że prawidłowo przeprowadzasz transakcje (z włączonym autouzależnianiem lub autocommitem i faktycznie obsługują zatwierdzanie/wycofywanie). – localshred

+0

Zdecydowanie dobry punkt; tak bywało przez większość czasu, ale tak naprawdę nie robimy transakcji na tym stole. Kiedyś, ale już nie. – ChrisInEdmonton

Odpowiedz

4

Podczas wykonywania operacji, InnoDBDML zamki wszystkie wiersze zeskanowane, nie dopasowane.

Rozważmy następujący układ tabeli:

DROP TABLE t_tran; 

CREATE TABLE t_tran (id INT NOT NULL PRIMARY KEY, data INT NOT NULL, KEY ix_tran_data (data)) Engine=InnoDB; 

DROP TABLE t_tran; 

CREATE TABLE t_tran (id INT NOT NULL PRIMARY KEY, data INT NOT NULL, KEY ix_tran_data (data)) Engine=InnoDB; 

INSERT 
INTO t_tran 
VALUES 
(1, 1), 
(2, 2), 
(3, 3), 
(4, 4), 
(5, 5), 
(6, 6), 
(7, 7), 
(8, 8); 

START TRANSACTION; 

DELETE 
FROM t_tran 
WHERE data = 2 
     AND id <= 5; 

w tym przypadku MySQL wybiera RANGE ścieżkę dostępu na id, które uzna za tańsze niż REF na data.

W równoległej transakcji, będzie można usunąć lub aktualizować wiersze 6, 7, 8, ale nie wierszy 1 do 5 ponieważ są one zamknięte (mimo że tylko rzędzie 2 wpłynęła).

Jeśli usuniesz id <= 5 z powyższego warunku, będziesz mógł usunąć dowolny wiersz oprócz wiersza 3.

Niestety, nie można kontrolować ścieżek dostępu MySQL w operacjach DML.

Najlepsze, co możesz zrobić, to poprawnie zindeksować swoje warunki i mieć nadzieję, że MySQL wybierze te indeksy.

+0

Dziękuję, my (mój sysadmin i ja) jesteśmy zdania, że ​​jest to prawdopodobnie najlepsza poprawka. Zmniejszyliśmy także liczbę usuwanych i dodawanych wykładniczych spadków. Zobaczymy, czy to rozwiąże problem. – ChrisInEdmonton

1

Upewnij się, że izolacja transakcji jest oznaczona jako przeczytana i nieodwracalna. Read commited powinien być domyślny, ale widzieliśmy, że na naszym serwerze domyślną wartością innodb był readable.

można sprawdzić, uruchamiając następujące:

SHOW VARIABLES LIKE 'tx%'; 

W celu ustalenia tego, w pliku my.cnf wprowadzić linię folloiwing:

tx_isolation=READ-COMMITTED