Úvod
merql je čistá knižnica PHP na trojstranné zlúčenie stavu databázy. Vytvára snímky tabuliek, počíta množiny zmien medzi snímkami, porovnáva dve množiny zmien so spoločným základom a zisťuje konflikty na úrovni stĺpcov. Používa rovnaký algoritmus ako git pri zdrojových súboroch, ale pracuje s riadkami a stĺpcami namiesto riadkov textu.
Bez externých nástrojov. Podporuje MySQL a SQLite prostredníctvom vymeniteľných adaptérov pripojenia a ovládačov dialektov.
Rýchly príklad
Zlúčenie potrebuje tri stavy tých istých údajov: base, z ktorého vychádzali obe kópie, a dve kópie po ich nezávislých zmenách. V tomto príklade bola testovacia kópia vytvorená z produkčnej databázy a odvtedy sa obe upravovali.
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";
}
Každá snímka sa vytvorí z databázy, ktorá obsahuje príslušný stav. Vytvorenie všetkých troch snímok postupne z jednej databázy nepredstavuje dve rozvetvené kópie: theirs by už obsahoval zmeny ours a každý riadok vložený v ours by bol nahlásený ako konflikt insert_insert.
Výsledok obsahuje operácie, ktoré prevedú base na zlúčený stav, zozbierané z oboch strán a označené zdrojom (ours, theirs alebo merged). Ak chcete zapísať zmeny testovacieho prostredia do produkcie, použite Kontrolované použitie iba pre operácie, ktoré v produkcii ešte chýbajú.
Alebo z CLI, ktorá sa pripája k databáze pomenovanej v MERQL_DB_DSN pre každý snapshot:
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
Prečo merql
Väčšina databázových nástrojov na porovnávanie stavov pracuje na úrovni riadkov: ak sa medzi dvoma verziami líši ktorýkoľvek stĺpec v riadku, celý riadok sa označí ako konflikt. To vedie k falošným konfliktom, keď dvaja ľudia upravia rôzne stĺpce toho istého riadka.
merql vykonáva zlúčenie na úrovni stĺpcov. Ak jedna strana zmenila title a druhá status, tieto zmeny sa zlúčia bez konfliktu. Konflikt sa nahlási iba vtedy, keď obe strany zmenia ten istý stĺpec na rôzne hodnoty.
Pri stĺpcoch TEXT a JSON môže merql zájsť o úroveň nižšie a zlúčiť obsah jednotlivých buniek. Dve úpravy rôznych riadkov textového stĺpca alebo rôznych kľúčov stĺpca JSON sa dajú zlúčiť rovnakým trojstranným algoritmom. Zlučovanie na úrovni buniek je voliteľné: odovzdajte CellMergeConfig do ThreeWayMerge. Fasáda Merql a príkaz CLI vykonávajú zlúčenie iba na úrovni stĺpcov. Pozrite si Zlučovanie na úrovni buniek.
Model zlúčenia
Base (snapshot at fork time)
/ \
Ours (one copy's changes) Theirs (the other copy's changes)
\ /
--------- MERGE ----------
|
Merged result
+ conflicts (if any)
Tri stavy, rovnako ako v git. Base je spoločný predok. Ours a theirs sú dve kópie po rozvetvení, pričom každá sa zachytáva z vlastnej databázy. Pravidlá zlúčenia zaobchádzajú s oboma stranami rovnako. Ich názvy sa objavujú v source každej operácie, v typoch konfliktov (update_delete znamená, že ours aktualizovalo riadok a theirs ho odstránilo) a v pravidlách riešenia OursWins a TheirsWins. Bez spoločného základu nemožno rozlíšiť „pridané“ od „nezmenené“.
Zlúčenie samo nič nezapisuje. Jeho operácie transformujú base na zlúčený stav, preto ich Merql::apply() možno vykonať bez problémov iba v databáze, ktorá stále obsahuje base. Ak chcete preniesť zmeny jednej strany do databázy, ktorá už obsahuje zmeny druhej strany, napríklad presunúť úpravy testovacieho prostredia do produkcie, použite iba operácie, ktoré jej chýbajú; pozrite si Kontrolované použitie.
Požiadavky
- PHP 8.2 alebo novší.
ext-mbstringaext-zlib, ktoré vyžaduje závislosťpitmaster/pitmasterposkytujúca rozdiely v texte.- Rozšírenie databázy pre používaný adaptér:
ext-pdosext-pdo_sqlitealeboext-pdo_mysql, prípadneext-mysqli.composer.jsonmerql iba odporúčaext-pdoaext-mysqli, preto ich Composer nekontroluje. - Databáza MySQL alebo SQLite. Ostatné databázové systémy vyžadujú vlastný ovládač.
Čo to nie je
merql nie je nástroj na migráciu schémy. nereplikuje databázy ani ich nesynchronizuje v reálnom čase. Rieši jeden konkrétny problém: z troch stavov databázy vytvorí štvrtý, zlúčený stav a identifikuje konflikty.
Dokumentácia
- Úvod -- inštalácia, prvá snímka, prvé zlúčenie.
- CLI Referencia -- úplná referencia príkazu
vendor/bin/merql. - PHP API Referencia -- úplná dokumentácia API všetkých tried.
- Plány zlúčenia -- stabilné ID operácií, skupiny zmien a výbery.
- Kontrolované použitie -- vybrané zápisy s podmienkami pre aktuálny stav riadka.
- Vrátenie zmien -- artefakty na vrátenie zmien a kontroly odchýlok.