Preskoči na vsebino

Uvod

merql je čista knjižnica PHP za trosmerno združevanje stanj podatkovne zbirke. Ustvari posnetke tabel, izračuna nabore sprememb med posnetki, združi dva nabora sprememb glede na skupno osnovo in zazna spore na ravni stolpcev. Uporablja isti algoritem kot git za izvorne datoteke, le da namesto vrstic obdeluje zapise in stolpce.

Brez zunanjih orodij. Podpira MySQL in SQLite prek prilagodljivih povezovalnih adapterjev in gonilnikov za dialekte.

Kratek primer

Za združitev potrebujete tri stanja istih podatkov: osnovo, iz katere sta izšli obe kopiji, in obe kopiji po njunih neodvisnih spremembah. Tukaj je bilo testno okolje kopirano iz produkcijske podatkovne zbirke, od takrat pa sta bili obe spremenjeni.

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";
}

Vsak posnetek se ustvari iz podatkovne zbirke, ki vsebuje to stanje. Če vse tri posnetke zaporedoma ustvarite v eni podatkovni zbirki, ne dobite dveh razšlih se kopij: njihova kopija bi že vsebovala naše spremembe, vsaka vrstica, ki smo jo dodali, pa bi bila označena kot spor insert_insert.

Rezultat navede operacije z obeh strani, ki osnovo pretvorijo v združeno stanje, pri čemer je vsaka označena s svojim virom (ours, theirs ali merged). Če želite spremembe iz testnega okolja zapisati v produkcijsko okolje, z orodjem Zaščitena uporaba uveljavite operacije, ki jih v produkcijskem okolju še ni.

Ali iz CLI, ki se poveže s podatkovno zbirko, navedeno v MERQL_DB_DSN za vsak snapshot:

Lupina
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

Zakaj merql

Večina orodij za primerjavo stanj podatkovnih zbirk deluje na ravni vrstic: če se med dvema različicama razlikuje kateri koli stolpec v vrstici, je celotna vrstica označena kot spor. To povzroči lažne spore, kadar dve osebi urejata različna stolpca iste vrstice.

merql združuje na ravni stolpcev. Če je ena stran spremenila title, druga pa status, se spremembe združijo brez spora. Spor nastane le, če obe strani spremenita isti stolpec na različni vrednosti.

Za stolpca TEXT in JSON lahko merql združevanje poglobi na raven celic. Dve spremembi različnih vrstic v besedilnem stolpcu ali različnih ključev stolpca JSON se lahko brez težav združita z istim trosmernim algoritmom. Združevanje na ravni celic je izbirno: posredujte CellMergeConfig v ThreeWayMerge. Vmesnik Merql in CLI združujeta samo na ravni stolpcev. Glejte Združevanje na ravni celic.

Model združevanja

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

Tri stanja, enako kot pri git. Osnova je skupni prednik. Naši in njihovi podatki sta kopiji po razhajanju, vsaka zajeta iz svoje podatkovne zbirke. Pravila združevanja obe strani obravnavajo enako. Imena se pojavijo v source vsake operacije, pri vrstah sporov (update_delete pomeni, da smo mi posodobili, oni pa izbrisali) ter v pravilih razreševanja OursWins in TheirsWins. Brez skupne osnove ni mogoče razlikovati med »dodano« in »nespremenjeno«.

Združitev sama po sebi ničesar ne zapiše. Njene operacije pretvorijo osnovo v združeno stanje, zato jih Merql::apply() uspešno izvede samo v podatkovni zbirki, ki še vedno vsebuje osnovo. Če želite spremembe ene strani prenesti v podatkovno zbirko, ki že vsebuje spremembe druge strani, na primer spremembe iz testnega okolja v produkcijsko, uveljavite samo operacije, ki ji manjkajo; glejte Zaščitena uporaba.

Zahteve

  • PHP 8.2 ali novejša različica.
  • ext-mbstring in ext-zlib, ki ju zahteva odvisnost pitmaster/pitmaster za prikaz razlik v besedilu.
  • Razširitev podatkovne zbirke za adapter, ki ga uporabljate: ext-pdo z ext-pdo_sqlite ali ext-pdo_mysql oziroma ext-mysqli. Konfiguracija composer.json za merql predlaga samo ext-pdo in ext-mysqli, zato jih Composer ne preverja.
  • Podatkovna zbirka MySQL ali SQLite. Za druge pogone potrebujete prilagojen gonilnik.

Kaj ni

merql ni orodje za selitev shem. Ne podvaja podatkovnih zbirk in jih ne sinhronizira v realnem času. Rešuje eno samo težavo: iz treh stanj podatkovne zbirke ustvari četrto, združeno stanje, in označi spore.

Dokumentacija