Miten skeemamuutoksia hallitaan pilvisovelluksissa?
Pilvipalvelussa tietokannan skeeman muuttaminen näyttää usein pieneltä työltä. Lisätään yksi sarake, vaihdetaan kentän tyyppiä tai poistetaan vanha taulu. Kehitysympäristössä muutos menee läpi, testit näyttävät vihreää ja käyttöönotto vaikuttaa suoraviivaiselta.
Tuotannossa tilanne voi olla aivan toinen.
Sama tietokanta voi palvella useita sovellusversioita yhtä aikaa. Taustalla voi pyöriä vanha API, uusi selainversio, ajastettu taustatyö ja jokin integraatio, jonka olemassaoloa ei enää muisteta. Lisäksi pilviympäristössä tietokanta ei välttämättä ole ainoa paikka, jossa kyseinen tieto esiintyy. Dataa voidaan kopioida välimuisteihin, tapahtumajonoihin, analytiikkapalveluihin ja muihin järjestelmiin.
Siksi schema change eli tietokannan skeeman muutos ei ole pelkkä SQL-tehtävä.
Ongelma syntyy yleensä silloin, kun sovellus olettaa vanhan rakenteen olevan olemassa samaan aikaan kun jokin toinen osa järjestelmää käyttää jo uutta rakennetta.
Hyvin suunniteltu muutos tehdäänkin vaiheittain. Vanhaa ja uutta rakennetta voidaan joutua tukemaan rinnakkain jonkin aikaa, jotta käyttöönotto voidaan tehdä ilman katkosta.
Skeeman muuttaminen on enemmän kuin tietokannan muutos
Yksinkertaisessa sovelluksessa yhteys on helppo nähdä:
sovellus → tietokanta.
Pilvisovelluksessa ketju on usein pidempi. Sovellus voi kirjoittaa tietokantaan, julkaista tapahtuman viestijonoon ja lähettää samalla tietoa toiselle palvelulle. Toinen palvelu voi käyttää samaa dataa omassa tietokannassaan.
Kun esimerkiksi customer_status-kentän rakennetta muutetaan, muutos ei välttämättä rajoitu siihen tietokantaan, jossa kenttä sijaitsee.Ongelma alkaa myöhemmin.
Ajatellaan tilannetta, jossa nykyinen kenttä sisältää arvot: active, inactive, pending
Uudessa versiossa halutaan tarkempi rakenne. Yksi merkkijono ei enää riitä, vaan asiakkaan tila ja syy erotetaan toisistaan.
Vanha sovellus odottaa edelleen:
customer_status = “active”
Uusi sovellus taas käyttää esimerkiksi:
status = “active”
status_reason = “verified”
Jos uusi rakenne otetaan käyttöön liian nopeasti, vanha sovellus ei välttämättä ymmärrä uutta dataa. Vielä hankalampi tilanne syntyy, jos uusi sovellus kirjoittaa uutta rakennetta ja vanha sovellus jatkaa samalla kirjoittamista vanhaan kenttään.
Tällaiset ongelmat eivät välttämättä näy heti. Ne voivat tulla esiin vasta tietyn liiketoimintaprosessin aikana.
Miksi pilvi tekee schema-muutoksista hankalampia?
Pilvi itsessään ei riko tietokannan muutoksia. Se kuitenkin tekee järjestelmistä helposti hajautettuja.
Sama sovellus voi olla käytössä useassa instanssissa. Käyttöönotto tehdään rolling deploymentina tai blue-green-mallilla. Uusi versio käynnistyy ennen kuin vanha on kokonaan poistunut.
Tämä tarkoittaa, että hetken aikaa tuotannossa voi olla:
vanhoja sovellusinstansseja
uusia sovellusinstansseja
vanha tietokantamalli
uusi tietokantamalli
käynnissä olevia taustatöitä
jonossa olevia viestejä.
Juuri tämä siirtymävaihe kannattaa suunnitella etukäteen.
Moni schemaongelma ei synny lopullisesta rakenteesta. Se syntyy muutoksen aikana.
Turvallisin lähtökohta: uusi rakenne ensin, vanha vielä käyttökelpoisena
Yksi käytännöllinen tapa tehdä muutoksia on niin sanottu expand-and-contract-malli.
Ajatus on melko yksinkertainen.
Ensin tietokantaan lisätään uusi rakenne rikkomatta vanhaa. Sen jälkeen sovellus alkaa käyttää uutta rakennetta. Kun kaikki tarvittavat palvelut on siirretty käyttämään sitä, vanha rakenne voidaan poistaa.
Esimerkiksi vanhaan customers-tauluun halutaan uusi preferred_language-kenttä.
lisätään kenttä
muutetaan sovellus
poistetaan vanha kenttä
julkaistaan uusi versio.
Huono tapa olisi tehdä kaikki kerralla:
uusi sarake lisätään
vanhat sovellusversiot jatkavat toimintaansa
uusi sovellus alkaa kirjoittaa uuteen sarakkeeseen
olemassa olevat tiedot täydennetään
lukeminen siirretään käyttämään uutta kenttää
vanhan rakenteen käyttöä seurataan
vanha kenttä poistetaan vasta myöhemmin.
Parempi eteneminen voi olla:
Tämä kuulostaa hitaammalta. Tuotannossa se on usein nopeampi tapa päästä perille, koska yksi huonosti suunniteltu tietokantamuutos voi aiheuttaa paljon enemmän työtä kuin ylimääräinen siirtymävaihe.
Nullable-sarake ei ole vain pieni tekninen yksityiskohta
➠ Uuden sarakkeen lisääminen on helppoa, jos se saa olla tyhjä.
➠ Tilanne muuttuu, jos vaatimus on:
preferred_language VARCHAR(10) NOT NULL
➠ ja taulussa on miljoonia olemassa olevia rivejä.
➠ Tietokanta joutuu huomioimaan kaikki vanhat rivit. Toteutustapa riippuu tietokantamoottorista ja versiosta, mutta isoilla tauluilla tällainen muutos voi vaikuttaa lukituksiin, levytilaan, suorituskykyyn tai migraation kestoon.
➠ Siksi tuotannossa ei kannata ajatella vain sitä, miltä migration-tiedosto näyttää.
➠ Oleellisempi kysymys on: mitä tietokanta joutuu oikeasti tekemään?
➠ Jos taulussa on muutama tuhat riviä, ongelmaa ei välttämättä ole. Jos rivejä on satoja miljoonia, sama muutos voi olla aivan eri luokan operaatio.
Sarakkeen lisääminen on helppoa. Sarakkeen poistaminen on eri asia.
Vanhan kentän poistaminen näyttää usein harmittomalta:
ALTER TABLE … DROP COLUMN …
Mutta ennen sitä pitäisi tietää, kuka kenttää vielä käyttää.
Käyttö ei välttämättä löydy pelkästä pääsovelluksesta.
Kenttää voi käyttää esimerkiksi:
vanha API-versio
raportointikysely
taustatyö
integraatio
ETL-prosessi
analytiikkaputki
hallintatyökalu
toinen palvelu.
Erityisen hankala tapaus on sovellus, joka rakentaa SQL-kyselyitä dynaamisesti. Silloin kentän käyttöä ei aina löydy yksinkertaisella haulla lähdekoodista.
Tästä syystä poistaminen kannattaa tehdä vasta sen jälkeen, kun vanhan rakenteen käyttö on todettu loppuneeksi.
ORM ei poista schema-muutosten riskiä
Hibernate, JPA, Entity Framework tai muu ORM voi helpottaa sovelluksen kehitystä. Se ei kuitenkaan tarkoita, että tietokannan rakenne olisi automaattisesti turvassa.
Esimerkiksi Java-sovelluksessa entity voi näyttää tältä: @Entity
public class Customer {
@Id
private Long id;
private String name;
private String preferredLanguage;
}
Koodin muuttaminen ei vielä muuta tuotantotietokantaa turvallisesti.
Jos ORM:n automaattinen schema update jätetään vastuuseen tuotantoympäristön muutoksista, kontrolli tietokannan rakenteeseen voi jäädä liian heikoksi. Yritysympäristössä migraatiot kannattaa yleensä tehdä hallitusti versionhallittujen migration-tiedostojen avulla.
Työkalu voi olla esimerkiksi Flyway tai Liquibase. Olennaista ei ole tietyn työkalun valinta, vaan se, että tietokantamuutoksilla on selkeä historia ja ne voidaan toistaa eri ympäristöissä.
Migraation pitäisi olla osa julkaisua, ei käsin tehtävä ylläpitotoimi
Tuotantotietokannan muuttaminen käsin on yksi niistä asioista, jotka toimivat pitkään hyvin — kunnes eivät enää toimi.
Jos kehittäjä käy suorittamassa SQL-komennon suoraan tuotantoon, muutos voi jäädä pois testistä, stagingista tai toisesta ympäristöstä.
Myöhemmin kukaan ei välttämättä tiedä tarkasti:
milloin muutos tehtiin
miksi se tehtiin
missä ympäristöissä se on tehty
voiko komennon suorittaa uudelleen
mitä seuraava julkaisu olettaa tietokannan rakenteesta.
Versionhallittu migraatio ratkaisee suuren osan tästä ongelmasta.
Tietokannan rakenne kulkee tällöin sovelluskoodin mukana. Uusi sovellusversio tietää, mitä tietokantaversiota se tarvitsee.
Tämä on erityisen tärkeää CI/CD-putkissa.
Taaksepäin yhteensopivuus ratkaisee paljon
➠ Pilvisovelluksen uusi versio ei saa yleensä olettaa, että kaikki muu järjestelmä vaihtuu samalla sekunnilla.
➠ Jos uusi sovellus alkaa kirjoittaa kokonaan uutta rakennetta, vanhan version pitää pystyä toimimaan siirtymävaiheen ajan.
➠ Tässä auttaa backward compatibility.
➠ Yksi tavallinen ratkaisu on kirjoittaa väliaikaisesti sekä vanhaan että uuteen kenttään.
➠ Esimerkiksi vanhan:
full_name
rinnalle lisätään:
first_name
last_name
➠ Uusi sovellus voi kirjoittaa molemmat. Vanha sovellus käyttää edelleen full_name-kenttää.
➠ Kun kaikki palvelut on päivitetty, vanhan kentän käytöstä voidaan luopua.
➠ Tämä lisää hetkellisesti sovelluskoodia. Vastineeksi käyttöönotto voidaan tehdä ilman, että kaikkien komponenttien täytyy päivittyä samassa hetkessä.
Datan backfill kannattaa suunnitella erikseen
Uusi sarake voi olla teknisesti olemassa, mutta vanhoissa riveissä ei ole vielä tietoa.
Silloin tarvitaan backfill.
Pienessä taulussa tämän voi tehdä yhdellä SQL-lauseella. Suuressa tuotantotietokannassa asia kannattaa miettiä tarkemmin.
Jos miljoonien rivien päivitys tehdään yhtenä valtavana transaktiona, seurauksena voi olla pitkä lukitus, suuri levykuorma tai muuta ylimääräistä kuormaa.
Usein parempi vaihtoehto on käsitellä dataa erissä.
Sopiva eräkoko riippuu tietokannasta ja työkuormasta. Tärkeää on, ettei backfillistä tehdä vahingossa tuotannon raskainta työvaihetta.
Myös epäonnistuneen ajon jatkaminen kannattaa huomioida. Jos prosessi pysähtyy 63 prosentin kohdalla, sen ei pitäisi vaatia koko työn aloittamista alusta.
Tietokannan migraatio ja datan migraatio ovat eri asioita
Nämä menevät helposti sekaisin.
Schema migration muuttaa rakennetta.
Data migration muuttaa olemassa olevan tiedon uuteen muotoon.
Esimerkiksi uuden sarakkeen lisääminen on schema-muutos. Vanhojen miljoonien asiakasrivien täyttäminen uuden sarakkeen arvoilla on datamigraatio.
Niitä ei aina kannata tehdä samalla kertaa.
Jos molemmat yhdistetään yhdeksi valtavaksi deployment-vaiheeksi, epäonnistumisen vaikutus kasvaa. Rakenteen lisääminen voidaan tehdä ensin ja datan siirto myöhemmin hallittuna taustatyönä.
Kun tietomalli muuttuu, myös tapahtumat voivat rikkoutua
Pilviympäristössä tietokanta ei ole aina järjestelmän ainoa tiedonlähde.
Monissa arkkitehtuureissa sovellus julkaisee tapahtumia esimerkiksi Kafkaan, Amazon EventBridgeen, Amazon SQS:ään tai muuhun viestijärjestelmään.
Jos tapahtuman rakenne muuttuu, vanhat kuluttajat voivat hajota.
Esimerkiksi vanha tapahtuma: {
“customerId”: 123,
“status”: “active”
}
Uusi versio voi käyttää: {
“customerId”: 123,
“status”: {
“code”: “active”,
“source”: “verified”
}
}
Vanha kuluttaja odottaa merkkijonoa. Se ei välttämättä pysty käsittelemään objektia.
Tietokannan schema-muutos voi siis johtaa ongelmaan toisessa järjestelmässä, vaikka tietokanta itsessään toimisi täydellisesti.
Tässä kohtaa versionointi auttaa. Tapahtumalle voidaan määritellä uusi versio tai rakenne voidaan muuttaa siten, että vanhat kuluttajat toimivat edelleen.
API:n schema on yhtä tärkeä kuin tietokannan schema
Sama ajattelu koskee REST- ja GraphQL-rajapintoja.
Jos API palauttaa:
{
“name”: “Matti”,
“status”: “active”
}
ja uusi versio poistaa status-kentän, joku asiakasohjelma voi edelleen odottaa sitä.
Siksi API-muutoksissa kannattaa erottaa toisistaan lisäys ja rikkova muutos.
Uuden vapaaehtoisen kentän lisääminen on yleensä helppo muutos.
Kentän poistaminen tai tietotyypin muuttaminen on eri asia.
muutos on asiakkaalle näkyvä. Kaikkien kuluttajien pitää tietää siitä.
Tuotannossa tällaisia muutoksia kannattaa tehdä samalla periaatteella kuin tietokantamigraatioita: ensin yhteensopiva uusi rakenne, sitten kuluttajien siirto ja vasta lopuksi vanhan poistaminen.
Null, tyhjä arvo ja puuttuva kenttä eivät ole sama asia
➠ Tämä aiheuttaa yllättävän paljon ongelmia.
➠ Tietokannassa voi olla:
NULL
➠ API:ssa kenttä voi olla kokonaan puuttuva:
{}
tai mukana tyhjänä:
{
“phone”: null
}
➠ Joissakin järjestelmissä näillä on eri merkitys.
➠ Kun schema muuttuu, kannattaa määritellä tämä tarkasti. Muuten yksi palvelu voi tulkita puuttuvan kentän tarkoittavan “ei tietoa”, kun toinen tulkitsee sen tarkoittavan “poista nykyinen arvo”.
➠ Tämä on pieni yksityiskohta, mutta tuotannossa pienet erot muuttuvat helposti datavirheiksi.
Schema Registry voi olla tarpeen tapahtumapohjaisessa ympäristössä
Jos organisaatiossa käytetään paljon tapahtumia, pelkkä dokumentaatio ei aina riitä.
Schema Registry voi auttaa hallitsemaan tapahtumien rakenteita ja yhteensopivuutta. Tällöin tuottaja ja kuluttaja eivät ole täysin riippuvaisia siitä, että kaikki muistavat oikean JSON-rakenteen.
Erityisen hyödyllistä tämä on silloin, kun tapahtumia kulkee useiden tiimien omistamien palveluiden välillä.
Silloin kysymys ei ole enää vain siitä, mitä yksi sovellus tietää datasta. Kyse on yhteisestä sopimuksesta palveluiden välillä.
Mitä tapahtuu rolling deploymentin aikana?
Tämä on yksi tärkeimmistä asioista, joka kannattaa testata ennen tuotantoa.
Oletetaan, että vanha versio käyttää:
email
ja uusi versio käyttää:
email_address.
Jos uusi tietokanta sisältää vain uuden kentän ja deployment tehdään vähitellen, osa instansseista käyttää yhtä kenttää ja osa toista.
Tällainen tilanne voi kestää minuutteja tai pidempään riippuen käyttöönotosta.
Siksi migraation pitää olla yhteensopiva kaikkien samanaikaisesti käynnissä olevien versioiden kanssa.
Hyvä testi onkin hyvin konkreettinen:
“Toimiiko vanha sovellusversio tietokannan uuden rakenteen kanssa?”
Jos vastaus on ei, migraatio ei välttämättä sovi suoraan rolling deploymentiin.
Zero-downtime ei tarkoita, ettei muutoksessa olisi riskiä
Käyttöönotto voidaan tehdä ilman palvelukatkoa ja silti aiheuttaa käyttäjille ongelmia.
Esimerkiksi tietokanta voi olla teknisesti käytettävissä, mutta migration lukitsee suuren taulun niin pitkäksi aikaa, että sovelluksen kyselyt alkavat odottaa.
Käyttäjän näkökulmasta palvelu on silloin käytännössä alhaalla, vaikka palvelimet ja load balancer toimisivat normaalisti.
Siksi zero-downtime-muutoksissa pitää seurata myös tietokannan käyttäytymistä:
query latency
lock wait
connection poolin käyttö
CPU
I/O
aktiiviset transaktiot
virhemäärät.
Testiympäristö ei aina kerro totuutta
Schema-muutoksen testaaminen pienellä kehitystietokannalla antaa vain osan kuvasta.
Tuotannossa taulussa voi olla:
huomattavasti enemmän rivejä
vanhoja tietoja eri muodoissa
puuttuvia arvoja
harvinaisia tiloja
aktiivisia transaktioita
rinnakkaisia kirjoituksia.
Jos mahdollista, migration kannattaa testata tuotantoa muistuttavalla datamäärällä.
Erityisesti suorituskykyä muuttavat operaatiot kannattaa testata realistisella aineistolla.
“Migration kesti kehittäjän koneella kaksi sekuntia” ei kerro paljoakaan siitä, mitä tapahtuu 500 miljoonan rivin taulussa.
Rollback ei aina tarkoita migraation peruuttamista
Tässä kohtaa kannattaa olla tarkkana.
Sovelluksen rollback on usein helppo:
uusi versio → vanha versio.
Tietokannan rollback voi olla paljon vaikeampi.
Jos uusi versio on jo kirjoittanut tietoa uuteen rakenteeseen, vanhaan rakenteeseen palaaminen voi vaatia datan palauttamista tai muuntamista.
Siksi kaikille schema-muutoksille ei ole järkevää tehdä automaattista “undo”-migraatiota.
Usein turvallisempi malli on tehdä eteenpäin yhteensopiva muutos ja pitää vanha rakenne käytössä niin kauan, että uusi versio voidaan tarvittaessa poistaa ilman datan menetystä.
Tietokannan varmuuskopiot ja palautusmenettelyt ovat tässä eri asia. Backupista palauttaminen on viimeinen palautumiskeino, ei normaali schema-muutoksen rollback-strategia.
Entä jos muutos epäonnistuu kesken kaiken?
Tuotantoon vietävä migration pitäisi suunnitella myös epäonnistumista varten.
Jos migraatio pysähtyy puolivälissä, pitää tietää:
mikä osa muutoksesta ehti tapahtua
voiko migraation ajaa uudelleen
jäikö lukituksia päälle
muuttuiko datan rakenne osittain
voiko sovellus jatkaa toimintaansa.
Idempotentti tai turvallisesti uudelleen ajettava migration helpottaa ylläpitoa huomattavasti.
Myös lokit kannattaa säilyttää niin, että epäonnistumisen syy voidaan selvittää myöhemmin ilman arvailua.
Käytännöllinen tapa suunnitella schema-muutos
Hyvä suunnitelma ei tarvitse olla pitkä dokumentti. Sen pitää vain vastata muutamaan oikeaan kysymykseen.
Ensimmäiseksi selvitetään, mitä rakennetta ollaan muuttamassa ja kuka sitä käyttää.
Sen jälkeen katsotaan, onko muutos yhteensopiva nykyisen sovellusversion kanssa.
Seuraava kysymys koskee datamäärää. On aivan eri asia muuttaa pientä asetustaulukkoa kuin suurta tapahtumataulua.
Sitten päätetään, voidaanko muutos tehdä vaiheittain.
Jos voidaan, uusi rakenne tuodaan ensin tuotantoon ilman että vanha rikotaan. Sovellus päivitetään sen jälkeen. Vanhan rakenteen poistaminen jätetään viimeiseen vaiheeseen.
Tämä lähestymistapa ei ole näyttävä. Se on kuitenkin huomattavasti helpompi ylläpitää kuin yksi iso julkaisu, jossa tietokanta, sovellus, API ja taustaprosessit muuttuvat samanaikaisesti.
Esimerkki: vanhan osoiterakenteen muuttaminen
➠ Otetaan käytännön esimerkki.
➠ Sovelluksessa asiakkaan osoite on tällä hetkellä yhdessä kentässä:
address
➠ Kentän sisältö voi olla esimerkiksi:
Mannerheimintie 10, Helsinki
➠ Uudessa versiossa osoite halutaan jakaa osiin:
street
postal_code
city
country
➠ Jos vanha kenttä poistetaan heti, vanha sovellusversio ei enää toimi.
➠ Parempi eteneminen voisi olla seuraava.
➠ Uudet kentät lisätään tietokantaan. Vanha address jää vielä paikalleen.
➠ Uusi sovellus osaa käyttää uusia kenttiä, mutta vanhaa osoitekenttää voidaan edelleen lukea tarvittaessa.
➠ Vanhoille riveille tehdään erillinen datamigraatio. Sen aikana kannattaa myös käsitellä epäselvät osoitteet erikseen. Kaikkia vanhoja merkkijonoja ei välttämättä pystytä jakamaan luotettavasti automaattisesti.
➠ Kun uusi rakenne on käytössä ja vanhan kentän lukeminen on loppunut, vanha sarake voidaan myöhemmin poistaa.
➠ Tässä esimerkissä varsinainen tekninen SQL-muutos on helppo osa. Vaikeampi kysymys on vanhan datan laatu.
➠ Juuri tällaiset asiat jäävät helposti huomaamatta, jos schema-muutosta tarkastellaan vain tietokannan näkökulmasta.
Cloud-sovelluksessa myös välimuistit pitää huomioida
Jos data tallennetaan Redis-välimuistiin, CDN:ään tai sovelluksen omaan muistiin, schema-muutos voi vaikuttaa myös siihen.
Vanha välimuistimerkintä voi sisältää vanhan rakenteen.
Jos uusi sovellus yrittää lukea sitä vanhan version datamallilla, tuloksena voi olla virhe tai väärin tulkittu tieto.
Ratkaisu voi olla esimerkiksi cache keyn versionointi:
customer:v1:123
ja myöhemmin:
customer:v2:123
Tällöin uusi sovellus ei yritä tulkita vanhaa dataa uuden rakenteen mukaan.
Kaikissa järjestelmissä tämä ei ole tarpeen, mutta hajautetuissa sovelluksissa asia kannattaa ainakin huomioida.
Schema-muutoksen onnistumista pitää seurata julkaisun jälkeen
Migrationin päättyminen onnistuneesti ei tarkoita, että työ on valmis.
Julkaisun jälkeen kannattaa seurata, tapahtuiko jotain odottamatonta.
Esimerkiksi:
API:n virhemäärät
tietokantakyselyiden vasteajat
poikkeukset sovelluslokeissa
viestijonojen kasvaminen
taustatöiden epäonnistumiset
tietokannan connection pool
liiketoimintamittarit.
Jos uusi kenttä vaikuttaa esimerkiksi tilausten käsittelyyn, pelkkä HTTP 200 -määrä ei kerro koko totuutta.
Tekninen järjestelmä voinäyttää terveeltä samalla kun osa liiketoimintadatan käsittelystä epäonnistuu.
Mitä kannattaa välttää?
Yksi huono tapa on tehdä useita riippuvaisia muutoksia yhdellä kertaa.
Jos samalla deploymentilla vaihdetaan tietokannan rakennetta, API:n formaattia, tapahtuman schemaa ja taustaprosessin toimintaa, ongelman lähdettä on vaikea löytää, jos jokin menee pieleen.
Toinen ongelma on vanhan rakenteen poistaminen liian aikaisin.
Kolmas on olettaa, että testidata vastaa tuotantoa.
Neljäs on unohtaa järjestelmän ulkopuoliset kuluttajat.
Ja ehkä käytännössä vaarallisin oletus on tämä: “Kaikki palvelut päivitetään samaan aikaan.”
Hajautetussa pilviympäristössä sitä ei kannata pitää oletuksena, ellei arkkitehtuuri oikeasti takaa sitä.
Hyvä schema-muutos ei vaadi täydellistä järjestelmää
Kaikkea ei tarvitse suunnitella kuukausia etukäteen.
Pienessä sovelluksessa yksinkertainen migration voi olla täysin riittävä. Suuremmassa palvelussa sama muutos tarvitsee enemmän valmistelua, koska riippuvuuksia on enemmän.
Oleellista on suhteuttaa suunnittelu muutoksen vaikutukseen.
Jos lisätään yksi nullable-sarake pieneen tauluun, kyse ei ole samasta riskistä kuin jos vaihdetaan suuren asiakastietokannan avainrakenne.
Siksi myös schema-muutosten arvioinnissa kannattaa katsoa todellista ympäristöä eikä pelkästään SQL-komentoa.
Lopuksi
Pilvisovelluksen tietokannan rakenne ei ole irrallinen osa järjestelmää. Se liittyy sovelluskoodiin, API-sopimuksiin, tapahtumiin, taustatöihin, välimuisteihin ja dataan, joka on kertynyt vuosien aikana.
Suurin ongelma ei yleensä ole uuden sarakkeen lisääminen. Vaikeampi osa on siirtymä vanhasta rakenteesta uuteen niin, että järjestelmä toimii myös muutoksen aikana.
Siksi schema-muutoksia kannattaa ajatella siirtyminä, ei yksittäisinä SQL-operaatioina.
Kun uusi rakenne voidaan tuoda ensin, vanha rakenne pitää hetken rinnalla ja käytöstä poistaminen tehdään vasta myöhemmin, jää tuotantoon enemmän pelivaraa. Jos jokin menee pieleen, kaikkea ei tarvitse palauttaa lähtöpisteeseen yhdellä kertaa.
Hyvä schema-muutos on lopulta melko arkinen asia. Se ei riko vanhaa sovellusta, ei pakota kaikkia palveluita päivittymään samalla sekunnilla ja antaa ylläpidolle mahdollisuuden nähdä, mitä tuotannossa oikeasti tapahtuu.
Se on yleensä paljon arvokkaampaa kuin mahdollisimman lyhyt migration.