A tesztgépen még tökéletes volt, de az éles rendszeren hiányzik az adatbázis fele? Rémálom az élesítés? Beszélgessünk az adatbázis változások kezeléséről!

A probléma

A problémát szinte mindenki ismeri, aki dolgozott már adatbázisokkal. Teszt környezetben működik, éles környezetben nem. Hosszas debugolás után kiderül, hogy hiányzik egy mező, vagy akár egy egész tábla, az éles adatbázisból.

1. megoldás: change scriptek

A koncepció elég egyszerű: ha változtatnunk kell az adatbázisok, a változást végrehajtó SQL parancsot felírjuk egy fájlba, és csinálunk egy programot ami ezeket szépen sorrendben végrehajtja. Például lehet egy ilyen mappánk:

  • 0001.sql
  • 0002.sql

A migrációs program természetesen feljegyzi, hogy melyik migráció került már végrehajtásra, és csak az új migrációkat hajtja végre.

Ez a fajta rendszer teremt egy érdekes lehetőséget. Ha a migrációkat rendesen karban tartjuk, bármikor felhúzhatjuk „nulláról” az adatbázist. Ha jön egy új fejlesztő a céghez, adunk neki egy üres adatbázist és végrehajtjuk a migrációkat, és máris kezdhet dolgozni a kolléga. Ennek természetesen az az előkövetelménye, hogy minden változás benne legyen a scriptekben.

Ez a rendszer csak akkor működik jól, ha minden változást már fejlesztés közben is feljegyzünk a migrációs fájlokba! A legjobb, ha a fejlesztői adatbázis módosításait is kizárólag ezzel kezeljük!

Tudtad?
Az olyan programok, mint a MySQL Workbench, le tudják generálni a change fájlokat. Így csak át kell nézned, de nem kell kézzel megírnod őket!

2. megoldás: struktúra leírások

A change scriptekkel egy komoly probléma van: ha hiba csúszik a scriptek konzisztenciájába, nem tudjuk nulláról lefuttatni őket, valahol megakad a folyamat és máris meredeken esik az egész migrációs folyamat értéke, mert nem tudunk nulláról felhúzni egy adatbázist.

Éppen ezért a migrációkra létezik egy másik megoldás is: a változások helyett azt írjuk le, hogy milyen legyen az adatbázis szerkezete. Például így:

<table name="customers">
    <column type="int" autoincrement="true">id</column>
    <column type="varchar(255)">firstName</column>
    ...

A migrációs programnak ez alapján ki kell találnia, hogy mely oszlopokat, táblákat kell hozzáadni vagy törölni az adatbázisból.

Ennek a módszernek van egy hatalmas hátránya: ha például olyan változásunk van, amely egyik oszlopból másol át adatokat egy másikba, azt ebben nehezen tudjuk leképezni.

Összehasonlítás

Nézzük, hogy melyiknek mi az előnye, illetve a hátránya:

Change scriptek
Struktúra leírások
Pozitívumok
  • Könnyen lekövethető változások
  • Könnyen telepíthető fejlesztői adatbázisok
  • Egyszerű migrációs program
  • Garantált adatbázis struktúra
  • Könnyen telepíthető fejlesztői adatbázisok
Negatívumok
  • Fejlesztői fegyelmet követel
  • Az adatbázis-változások nem tranzakcionálisak, így hiba esetén előállhat inkonzisztens állapot.
  • Bonyolult migrációs program
  • Nem minden változás írható le vele

Óvatosan az olyan rendszerekkel, amelyek struktúra leírásokból generálnak change scripteket! (pl. Doctrine) Ezek a rendszerek időnként belezavarodnak a módosításokba, ezért érdemes átnézni a generált migrációs fájlokat.

Migrációk a gyakorlatban

A gyakorlatban szinte minden rendszer a change script megoldást használja. Ha szeretnénk bevezetni ezeket a migrációkat a rendszerünkbe, nincs más dolgunk, mint a jelenlegi adatbázis szerkezetet lementeni (pl. mysqldump --no-data) és betölteni az első migrációba.

Migrációs program gyanánt vagy használhatunk kész szoftvert (pl. Doctrine Migrations) vagy akár írhatunk sajátot is, ahogy a blog projekt kapcsán meg is tettük. Ebben a projektben mi egyszerűen felsoroltuk a migrációs osztályokat a konfig fájlunkban, a migrációs engine pedig szépen végig ment ezeken és végrehajtotta a benne levő SQL-eket. Így például a blog postok tábláját létrehozó migráció így néz ki:

class CreateBlogPostsTable extends Migration {
    function upgrade() {
        $this->getPDO()->query(/** @lang MySQL */
            '
            CREATE TABLE blogposts (
                slug VARCHAR(255) PRIMARY KEY,
                author VARCHAR(255) NOT NULL,
                title VARCHAR(255) NOT NULL,
                content MEDIUMTEXT NOT NULL,
                published_at DATETIME NOT NULL
            ) ENGINE=InnoDB;
            ');
    }
}

Egyszerű, ugye?

Tipp!
Az adataidat ne tárold a change scriptjeidben, vagy ha mégis, teremtsd meg a lehetőséget arra, hogy ezek nélkül is le lehessen futtatni a migrációkat!