Tietokannan deadlock on yksi niistä ongelmista, jotka eivät näy heti, mutta kun ne osuvat kohdalle, ne tuntuvat satunnaisilta, vaikeasti toistettavilta ja usein “mystisiltä”. WordPress-ympäristössä deadlockit ovat harvinaisia kevyessä käytössä, mutta kuormitetuissa, dynaamisissa ja integroiduissa järjestelmissä ne ovat täysin todellinen riski.
Deadlock ei ole bugi WordPressissä. Se on seuraus siitä, miten tietokantaa käytetään.
Mikä deadlock on
Deadlock syntyy, kun:
-
kaksi tai useampi transaktio lukitsevat resursseja
-
kukin odottaa toisen vapauttavan lukon
-
kukaan ei pääse etenemään
MySQL (InnoDB):
-
tunnistaa deadlockin
-
keskeyttää yhden transaktion
-
palauttaa virheen
WordPressissä tämä näkyy usein:
-
satunnaisina virheinä
-
epäonnistuneina päivityksinä
-
puuttuvina metatietoina
-
500-virheinä ilman selvää syytä
Miksi deadlockit ylipäätään syntyvät WordPressissä
WordPress ei käytä eksplisiittisiä transaktioita core-tasolla, mutta:
-
InnoDB käyttää automaattisia lukkoja
-
yksi pyyntö voi tehdä useita kirjoituksia
-
lisäosat lisäävät omia kyselyitään
Kun nämä tapahtuvat samanaikaisesti, deadlock on mahdollinen.
Tyypilliset deadlock-skenaariot
wp_postmeta ja wp_options
Yleisimmät kohteet:
-
wp_postmeta -
wp_options
Syitä:
-
paljon kirjoituksia samoihin post_id:ihin
-
autoload-optionien päivitykset
-
kilpailu cron-ajojen ja frontendin välillä
wp_options on erityisen herkkä, koska:
-
se on globaali
-
sitä luetaan ja kirjoitetaan jatkuvasti
-
yksi lukko vaikuttaa koko sivustoon
WooCommerce ja muut raskaat lisäosat
WooCommerce:
-
päivittää tilauksia
-
muokkaa varastotietoja
-
kirjoittaa useaan tauluun per pyyntö
Kun:
-
useita checkoutteja tapahtuu yhtä aikaa
-
varastosaldoja päivitetään rinnakkain
deadlockin todennäköisyys kasvaa merkittävästi.
Cron-ajot ja rinnakkaisuus
WordPress Cron:
-
ei ole oikea cron
-
voi käynnistyä useasta pyynnöstä
-
ei ole lukittu oletuksena
Tulos:
-
sama tehtävä voi ajaa kahdesti
-
molemmat yrittävät päivittää samoja rivejä
-
deadlock syntyy
Tämä on yksi aliarvioiduimmista syistä deadlock-tilanteille.
REST API ja AJAX
REST- ja AJAX-pyynnöt:
-
tapahtuvat rinnakkain
-
voivat muokata samoja resursseja
-
eivät “näe” toisiaan
Esimerkki:
-
frontend päivittää dataa AJAXilla
-
taustalla cron tai webhook tekee samaa
Tietokanta ei tiedä, kumpi on “oikea”, vain lukot ratkaisevat.
Miten deadlock näkyy käytännössä
MySQL error logissa:
-
Deadlock found when trying to get lock -
Transaction rollback
WordPressissä:
-
päivitys ei tallennu
-
data katoaa tai jää vajaaksi
-
käyttäjä ei näe virheilmoitusta
Usein deadlockit jäävät huomaamatta ilman lokitusta.
Miksi deadlock ei ole katastrofi (jos ymmärrät sen)
Tärkeä fakta:
-
MySQL ratkaisee deadlockin
-
yksi transaktio rollbackataan
-
tietokanta ei korruptoidu
Ongelma syntyy vasta, jos:
-
sovellus ei käsittele virhettä
-
logiikka olettaa onnistumisen
-
käyttäjälle ei näytetä palautetta
Deadlock on hallittava riski, ei kriisi.
Deadlockien ehkäisy WordPressissä
Vältä tarpeettomia kirjoituksia
-
älä päivitä optionia, jos arvo ei muutu
-
vältä “update on every page load” -malleja
-
cachetaa laskettu data
Kirjoitukset ovat aina riskialttiimpia kuin lukeminen.
Lyhennä kriittisiä jaksoja
-
tee laskenta ennen tietokantapäivitystä
-
pidä kirjoitukset mahdollisimman lyhyinä
-
älä tee useita päivityksiä per pyyntö ilman syytä
Mitä lyhyempi lukko, sitä pienempi deadlock-riski.
Serialisoi, kun on pakko
Joissain tapauksissa:
-
yksi resurssi kerrallaan
-
lukitus sovellustasolla
-
esimerkiksi object cacheen perustuva mutex
Tämä on viimeinen keino, mutta joskus välttämätön.
Cron oikeaksi croniksi
-
poista WP-Cron frontendista
-
käytä järjestelmän cronia
-
varmista, että tehtävät eivät aja päällekkäin
Tämä yksinään voi poistaa suuren osan deadlockeista.
Indeksit ja kyselyjärjestys
Huono indeksointi:
-
laajentaa lukkojen aluetta
-
hidastaa vapautumista
Hyvä indeksointi:
-
lukitsee vähemmän rivejä
-
vapauttaa nopeammin
-
pienentää deadlock-ikkunaa
Deadlock ei ole vain logiikkaongelma, vaan myös tietokantaongelma.
Miten deadlockeja kannattaa käsitellä koodissa
Hyvä käytäntö:
-
tunnista deadlock-virhe
-
yritä uudelleen kerran tai kaksi
-
logita tapahtuma
Useimmat deadlockit:
-
ratkeavat seuraavalla yrityksellä
-
eivät toistu heti
Paniikki ei auta, retry auttaa.
Multisite ja deadlockit
Multisite:
-
jakaa tauluja
-
lisää rinnakkaisuutta
-
kasvattaa lukitusaluetta
Yksi huonosti käyttäytyvä sivusto:
-
voi aiheuttaa ongelmia koko verkolle
Multisite vaatii erityistä kurinalaisuutta kirjoituksissa.
Milloin deadlock on merkki huonosta arkkitehtuurista
Deadlock ei ole aina virhe, mutta:
-
jos niitä tapahtuu jatkuvasti
-
jos ne osuvat samoihin tauluihin
-
jos ne aiheuttavat käyttäjävirheitä
silloin ongelma on:
-
liiallisessa kirjoittamisessa
-
väärässä vastuunjaossa
-
puuttuvassa cache-strategiassa
Lopuksi: deadlock on oire, ei vihollinen
WordPressin deadlock-tilanteet kertovat:
-
missä kuormitus oikeasti on
-
mitkä resurssit ovat kriittisiä
-
mitä pitäisi yksinkertaistaa
Kun deadlockeja ymmärtää, niitä ei tarvitse pelätä. Ne ovat tietokannan tapa sanoa: nyt teette liikaa samaan aikaan.
