WordPressin tietokantarakenne on joustava, mutta samalla siinä on yksi historiallinen ratkaisu, joka aiheuttaa paljon ongelmia: serialized data. Se on tapa tallentaa monimutkaisia tietorakenteita yhteen tietokenttään. Ratkaisu syntyi aikana, jolloin WordPressin piti olla kevyt, yksinkertainen ja helposti laajennettava, mutta nykyisessä mittakaavassa se voi aiheuttaa yllättäviä virheitä.
Serialized data -rikkoontuminen on yksi yleisimmistä, mutta vaikeimmin havaittavista WordPress-ongelmista. Sivusto voi toimia näennäisesti normaalisti, mutta yksittäiset toiminnot alkavat käyttäytyä oudosti. Syynä on usein yksi väärä merkki serialized-merkkijonossa.
Mitä serialized data tarkoittaa
PHP:ssä on sisäänrakennettu mekanismi nimeltä serialize, joka muuntaa taulukot ja objektit merkkijonoksi. Tämä merkkijono voidaan tallentaa tietokantaan ja palauttaa myöhemmin takaisin alkuperäiseen muotoonsa unserialize-funktion avulla.
Esimerkiksi taulukko:
array(
"nimi" => "Testi",
"ikä" => 30
)
Muuttuu serialized-muotoon:
a:2:{s:4:"nimi";s:5:"Testi";s:3:"ikä";i:30;}
Tämä näyttää sekavalta, mutta siinä on tarkka rakenne:
-
a:2tarkoittaa taulukkoa, jossa on kaksi elementtiä -
s:4:"nimi"tarkoittaa merkkijonoa, jonka pituus on 4 -
s:5:"Testi"tarkoittaa merkkijonoa, jonka pituus on 5
Tuo merkkijonon pituus on koko järjestelmän akilleenkantapää.
Missä WordPress käyttää serialized dataa
WordPress käyttää serialized dataa monissa paikoissa:
-
wp_options-taulussa
-
wp_postmeta-taulussa
-
wp_usermeta-taulussa
-
Widget-asetuksissa
-
Lisäosien konfiguraatioissa
Yksittäinen option-arvo voi sisältää kokonaisen asetusrakenteen, jossa on kymmeniä tai satoja arvoja.
Miksi serialized data rikkoutuu
Serialized data on herkkä muutoksille, koska merkkijonon pituus on kovakoodattu rakenteeseen. Jos merkkijono muuttuu, mutta pituus ei päivity, rakenne menee rikki.
Yleisin syy: hakeminen ja korvaaminen
Kun sivuston domain vaihdetaan, tietokannassa tehdään usein hakeminen ja korvaaminen:
-
vanha-domain.fi → uusi-domain.fi
Jos tämä tehdään tavallisella SQL-replace-komennolla, serialized data rikkoutuu.
Esimerkki:
Alkuperäinen:
s:16:"vanha-domain.fi";
Korvauksen jälkeen:
s:16:"uusi-domain.fi";
Mutta uusi merkkijono voi olla eri pituinen. Tällöin pituus ei vastaa sisältöä, ja unserialize epäonnistuu.
Miltä rikkinäinen serialized data näyttää
Oireet voivat olla yllättävän epämääräisiä:
-
Widgetit katoavat
-
Teema-asetukset nollautuvat
-
Lisäosat lakkaavat toimimasta
-
Admin-paneelissa näkyy tyhjiä arvoja
-
Sivusto näyttää osittain rikkinäiseltä
Usein virheilokia ei ole, tai siinä näkyy vain:
PHP Notice: unserialize(): Error at offset...
Tämä tarkoittaa, että serialized-merkkijonon rakenne on rikki.
UTF-8 ja monibyte-merkit
Serialized data ei rikkoudu vain domain-vaihdoissa. Myös merkkikoodaus voi aiheuttaa ongelmia.
Jos serialized data sisältää esimerkiksi ääkkösiä:
"ä", "ö", "å"
Ja tietokannan merkistökoodaus muuttuu, merkkijonon tavumäärä voi muuttua. PHP mittaa merkkijonon pituuden tavuina, ei kirjaimina.
Esimerkiksi:
-
”ä” voi olla yksi merkki
-
Mutta kaksi tavua UTF-8:ssä
Jos serialized data on luotu eri koodauksessa kuin missä sitä luetaan, pituus ei enää täsmää.
Objektien serialisointi
Tilanne monimutkaistuu entisestään, kun serialized data sisältää objekteja.
Esimerkki:
O:8:"stdClass":1:{s:4:"nimi";s:5:"Testi";}
Tämä kertoo:
-
Objektin nimi
-
Sen ominaisuudet
-
Niiden arvot
Jos objektin luokka ei ole saatavilla unserialize-vaiheessa, data voi rikkoutua tai palautua väärin.
Tämä tapahtuu usein, kun:
-
Lisäosa poistetaan
-
Teema vaihtuu
-
Luokkarakenne muuttuu päivityksessä
Rikkoontuminen massamuokkauksissa
Serialized data on erityisen haavoittuva massamuokkauksissa.
Tyypillisiä tilanteita:
-
Domain-vaihto
-
HTTPS-migraatio
-
CDN-osoitteiden vaihto
-
Polkujen muuttaminen
-
URL-rakenteen päivitys
Jos muutos tehdään suoraan SQL:llä, serialized data voi rikkoutua sadoissa riveissä yhdellä komennolla.
Se on vähän kuin yrittäisi vaihtaa kirjan sanoja ilman, että huomaa sivunumeroiden muuttuvan. Lopputuloksena sisällysluettelo ei enää vastaa todellisuutta.
Miten rikkoontuminen havaitaan
Serialized data -virheet eivät aina näy heti.
Yleisiä merkkejä:
-
Asetukset eivät tallennu
-
Widgetit palautuvat oletustilaan
-
Yksittäinen lisäosa toimii oudosti
-
Hakutoiminnot eivät toimi
Teknisesti tarkasteltuna:
-
unserialize palauttaa false
-
Tai heittää varoituksen
Tämä voi jäädä huomaamatta, jos koodi ei tarkista palautusarvoa.
Turvallinen hakeminen ja korvaaminen
Serialized dataa ei saa muokata tavallisella SQL-replace-komennolla.
Turvallinen tapa:
-
Data puretaan unserialize-funktiolla
-
Muutokset tehdään rakenteeseen
-
Data serialisoidaan uudelleen
Tämä varmistaa, että merkkijonojen pituudet pysyvät oikein.
JSON vaihtoehtona
Modernissa kehityksessä serialized dataa korvataan usein JSON-muodolla.
JSON:
-
Ei sisällä merkkijonopituuksia
-
On helpompi lukea
-
On yhteensopiva muiden kielten kanssa
Esimerkki:
{"nimi":"Testi","ikä":30}
Jos domain vaihtuu, JSON ei rikkoudu samalla tavalla kuin serialized data.
WordPress käyttää kuitenkin edelleen serialized dataa laajasti, koska:
-
Se on taaksepäin yhteensopiva
-
Monet lisäosat nojaavat siihen
-
Koko ekosysteemi on rakennettu sen varaan
Filosofinen sivupolku: tekninen velka ajassa
Serialized data on hyvä esimerkki teknisestä velasta. Se oli aikanaan järkevä ratkaisu:
-
Yksinkertainen
-
Nopea toteuttaa
-
Ei vaatinut monimutkaista tietokantarakennetta
Mutta kun järjestelmä kasvoi miljoonien sivustojen alustaksi, sama ratkaisu alkoi aiheuttaa ongelmia.
Se on vähän kuin vanha silta, joka rakennettiin hevoskärryille, mutta jonka yli kulkee nyt raskasta rekkaliikennettä. Silta ei ole väärin rakennettu. Se on vain rakennettu eri aikakauden tarpeisiin.
Yhteenveto
Serialized data -rikkoontuminen johtuu yleensä:
-
Domain-vaihdoista
-
Suorista SQL-replace-komennoista
-
Merkistökoodauksen muutoksista
-
Objektirakenteiden muutoksista
Ongelman ydin on merkkijonon pituustieto, joka menee epäsynkroniin sisällön kanssa.
Turvallisin lähestymistapa on:
-
Välttää suoraa SQL-replacea
-
Muokata dataa ohjelmallisesti
-
Testata muutokset ennen tuotantoon siirtoa
Serialized data ei ole paha keksintö, mutta se on herkkä. Se toimii täydellisesti niin kauan kuin sitä kohdellaan oikein. Heti kun siihen kosketaan väärällä työkalulla, rakenne voi hajota kuin kellokoneisto, josta on siirretty yksi hammasratas puoli milliä sivuun.
