Mam bardzo ruchliwą stronę internetową, na której co godzinę można wstawić tysiące nowych rekordów.
Ten jeden błąd paraliżuje witrynę:
PDOException: SQLSTATE[40001]: Serialization failure: 1213
Deadlock found when trying to get lock;
try restarting transaction: INSERT INTO {location_instance}
(nid, vid, uid, genid, lid) VALUES (:db_insert_placeholder_0,
:db_insert_placeholder_1, :db_insert_placeholder_2,
:db_insert_placeholder_3, :db_insert_placeholder_4);
Array ( [:db_insert_placeholder_0] => 1059 [:db_insert_placeholder_1] =>
1059 [:db_insert_placeholder_2] => 0 [:db_insert_placeholder_3] =>
cck:field_item_location:1059 [:db_insert_placeholder_4] => 1000 )
Byłbym bardzo zaskoczony, gdyby MySQL nie mógł poradzić sobie z tego typu obciążeniem. Zatem moje pytania brzmią: czy jest to problem z bazą danych i jak mogę skonfigurować MySQL, aby mógł obsługiwać tak duży ruch?
Mam kopię mojej witryny skonfigurowaną na serwerze programistycznym ze skryptami symulującymi obciążenie treści dodawanej do witryny. Korzystam z Ubuntu, stosu LAMP, z 16 GB pamięci RAM.
Trzeba przyznać, że nie mam zbyt dużej wiedzy na temat baz danych. W rzeczywistości zaczynam od domyślnego pliku my.cnf, który jest dołączany po zakończeniu instalacji „apt-get install”. Wszystkie tabele są Innodb. Jakie początkowe ustawienia konfiguracji i podejście poleciłbyś rozpocząć, aby rozwiązać ten problem?
Daj mi znać, jakich dodatkowych informacji możesz potrzebować.
Dzięki
Odpowiedzi:
Masz do czynienia z impasem, a nie problemem wąskiego gardła w zakresie wydajności.
Jeśli masz tysiąc nowych rekordów na godzinę, jesteś daleko od osiągnięcia limitów MySQL. MySQL może obsłużyć co najmniej 50 razy ładunek.
Zakleszczenia są powodowane przez kod aplikacji i nie są winą serwera bazy danych. Zakleszczeń nie można naprawić po stronie serwera MySQL, z wyjątkiem niektórych szczególnych sytuacji.
InnoDB
może wyświetlić szczegółowe informacje o zakleszczeniu, uruchamiającSHOW ENGINE INNODB STATUS
po znaku zachęty MySQL lub za pomocąmysql -uroot -p... -e "SHOW ENGINE INNODB STATUS"
.Jednak pokazuje to tylko ostatni zakleszczenie, które wystąpiło, nie ma dziennika zakleszczenia.
Na szczęście istnieje narzędzie pt-deadlock-logger, które zajmuje się tym problemem, dba o
InnoDB
status odpytywania i zapisuje wszystkie szczegółowe informacje o zakleszczeniu, zanim zostanie odświeżone z nowym impasem.źródło
Może to być tak proste, jak jedna część kodu prowadząca transakcję:
podczas gdy inna część kodu modyfikuje te same tabele w innej kolejności:
Jeśli obie transakcje przebiegają w tym samym czasie, może wystąpić wyścig: pierwsza transakcja nie może zostać zmodyfikowana,
t2
ponieważ jest zablokowana przez drugą transakcję; podczas gdy druga transakcja jest podobnie blokowana, ponieważt1
jest blokowana przez pierwszą transakcję. MySQL wybiera jedną transakcję jako „ofiarę”, w przypadku której INSERT / UPDATE / DELETE kończy się niepowodzeniem. Aplikacja musi wychwycić ten błąd i ponowić instrukcję - może po przerwie, aby druga transakcja miała czas na zakończenie. Nie ma to nic wspólnego z ograniczeniami pojemności, po prostu niefortunne taktowanie, które może być zaostrzone przez sposób ułożenia kodu. Przełączaj DELETE w transakcji nr 2 lub INSERT w transakcji nr 1, a wtedy nie będzie konfliktu - każda transakcja będzie oczekiwać na dostęp do potrzebnych tabel.W MySQL 5.6 można uruchomić z włączoną opcją innodb_print_all_deadlocks , aby zbierać informacje o wszystkich zakleszczeniach (nie tylko ostatnich) w dzienniku błędów MySQL.
[Obowiązkowe zastrzeżenie: Jestem pracownikiem Oracle. Powyższe jest moim osobistym poglądem, a nie oficjalnym oświadczeniem.]
źródło