Pereiti prie turinio

Įvadas

merql yra grynoji PHP biblioteka, atliekanti trijų krypčių duomenų bazės būsenos sujungimus. Ji sukuria lentelių momentines kopijas, apskaičiuoja pakeitimų rinkinius tarp jų, sujungia du pakeitimų rinkinius pagal bendrą bazę ir aptinka konfliktus stulpelių lygmeniu. Naudojamas tas pats algoritmas kaip git šaltinio failams, tik eilutėms ir stulpeliams, o ne kodo eilutėms.

Nereikia išorinių įrankių. Palaikomi MySQL ir SQLite naudojant prijungiamus ryšio adapterius ir dialektų tvarkykles.

Trumpas pavyzdys

Sujungimui reikia trijų tų pačių duomenų būsenų: bazinės, nuo kurios pradėjo abi kopijos, ir dviejų kopijų po nepriklausomų pakeitimų. Šiuo atveju bandomoji aplinka nukopijuota iš veikiančios duomenų bazės, o nuo tada pakeistos abi.

PHP
use Merql\Connection;
use Merql\Merql;

$live    = Connection::sqlite('/data/live.sqlite');
$sandbox = Connection::sqlite('/data/sandbox.sqlite');

// Base: live at the moment the sandbox was copied from it.
Merql::init($live);
Merql::snapshot('base');

// ... copy live.sqlite to sandbox.sqlite, then both databases change ...

// Ours: the sandbox with our edits. Theirs: live with its own changes.
Merql::init($sandbox);
Merql::snapshot('ours');
Merql::init($live);
Merql::snapshot('theirs');

$result = Merql::merge('base', 'ours', 'theirs');

if ($result->isClean()) {
    foreach ($result->operations() as $operation) {
        echo "{$operation->type} {$operation->table} #{$operation->rowKey} ({$operation->source})\n";
    }
} else {
    echo "Conflicts: {$result->conflictCount()}\n";
}

Kiekviena momentinė kopija sukuriama iš duomenų bazės, kurioje yra atitinkama būsena. Jei visas tris iš eilės sukursite iš vienos duomenų bazės, jos neatspindės dviejų atsiskyrusių kopijų: jų kopijoje jau bus mūsų pakeitimų, o kiekviena mūsų įterpta eilutė bus nurodyta kaip insert_insert konfliktas.

Rezultate išvardytos operacijos, kuriomis bazinė būsena paverčiama sujungta būsena; įtraukti abiejų pusių pakeitimai, o kiekviena operacija pažymėta jos šaltiniu (ours, theirs arba merged). Norėdami perkelti bandomosios aplinkos pakeitimus į veikiančią aplinką, naudokite Apsaugotą pritaikymą ir pritaikykite operacijas, kurių dar nėra veikiančioje aplinkoje.

Arba iš CLI, kuri prisijungia prie duomenų bazės, nurodytos MERQL_DB_DSN kiekvienai snapshot:

Shell
MERQL_DB_DSN="sqlite:/data/live.sqlite" vendor/bin/merql snapshot base
# ... copy live.sqlite to sandbox.sqlite, then both databases change ...
MERQL_DB_DSN="sqlite:/data/sandbox.sqlite" vendor/bin/merql snapshot ours
MERQL_DB_DSN="sqlite:/data/live.sqlite" vendor/bin/merql snapshot theirs

vendor/bin/merql merge base ours theirs --dry-run

Kodėl merql

Dauguma būseną lyginančių duomenų bazių įrankių veikia eilučių lygmeniu: jei bet kuris eilutės stulpelis skiriasi tarp dviejų versijų, visa eilutė pažymima kaip konfliktas. Dėl to klaidingai nurodomi konfliktai, kai du žmonės keičia skirtingus tos pačios eilutės stulpelius.

merql sujungia stulpelių lygmeniu. Jei viena pusė pakeitė title, o kita – status, pakeitimai sklandžiai sujungiami be konflikto. Konfliktas kyla tik tada, kai abi pusės pakeičia tą patį stulpelį į skirtingas reikšmes.

TEXT ir JSON stulpeliuose merql gali sujungti vienu lygmeniu giliau – langelių lygmeniu. Du skirtingų teksto stulpelio eilučių arba skirtingų JSON stulpelio raktų pakeitimai gali būti sklandžiai sujungti tuo pačiu trijų krypčių algoritmu. Langelių lygmens sujungimas pasirenkamas: perduokite CellMergeConfig į ThreeWayMerge. Merql fasadas ir CLI sujungia tik stulpelių lygmeniu. Žr. Sujungimas langelių lygmeniu.

Sujungimo modelis

Kodas
         Base (snapshot at fork time)
        /                              \
   Ours (one copy's changes)            Theirs (the other copy's changes)
        \                              /
         --------- MERGE ----------
                     |
              Merged result
              + conflicts (if any)

Trys būsenos, kaip ir git. Bazinė yra bendras protėvis. Mūsų ir jų kopijos yra dvi atsiskyrusios kopijos, kiekviena užfiksuota iš jai skirtos duomenų bazės. Sujungimo taisyklės abi puses traktuoja vienodai. Pavadinimai pateikiami kiekvienos operacijos source, konfliktų tipuose (update_delete reiškia, kad mes atnaujinome, o jie ištrynė) ir OursWins bei TheirsWins sprendimo strategijose. Neturint bendros bazės neįmanoma atskirti „pridėta“ nuo „nepakeista“.

Pats sujungimas nieko neįrašo. Jo operacijos bazinę būseną paverčia sujungta būsena, todėl Merql::apply() visas jas sėkmingai vykdo tik duomenų bazėje, kurioje tebėra bazinė būsena. Norėdami perkelti vienos pusės pakeitimus į duomenų bazę, kurioje jau yra kitos pusės pakeitimų, pavyzdžiui, perkelti bandomosios aplinkos pakeitimus į veikiančią aplinką, pritaikykite tik trūkstamas operacijas; žr. Apsaugotas pritaikymas.

Reikalavimai

  • PHP 8.2 arba naujesnė versija.
  • ext-mbstring ir ext-zlib, reikalingi pitmaster/pitmaster priklausomybei, kuri pateikia teksto skirtumų skaičiavimo funkciją.
  • Duomenų bazės plėtinys jūsų naudojamam adapteriui: ext-pdo su ext-pdo_sqlite arba ext-pdo_mysql, arba ext-mysqli. merql composer.json tik rekomenduoja įdiegti ext-pdo ir ext-mysqli, todėl Composer jų netikrina.
  • MySQL arba SQLite duomenų bazė. Kitoms sistemoms reikia pasirinktinės tvarkyklės.

Kas tai nėra

merql nėra schemos migravimo įrankis. Jis neatkuria duomenų bazių ir nesinchronizuoja jų realiuoju laiku. Jis sprendžia vieną konkrečią problemą: turint tris duomenų bazės būsenas, sukuria ketvirtą sujungtą būseną ir nurodo konfliktus.

Dokumentacija

  • Pradžia -- diegimas, pirmasis momentinis vaizdas, pirmasis sujungimas.
  • CLI Nuoroda -- išsami vendor/bin/merql komandos nuoroda.
  • PHP API nuoroda -- išsami API dokumentacija apie visas klases.
  • Sujungimo planai -- stabilūs operacijų ID, pakeitimų grupės ir pasirinkimai.
  • Apsaugotas taikymas -- pasirinktų pakeitimų įrašymas su tiesioginės eilutės išankstinėmis sąlygomis.
  • Atšaukimas -- atšaukimo artefaktai ir nukrypimų patikros.