Suojattu käyttöönotto
GuardedApplier ottaa puhtaan MergeResult-tuloksen käyttöön vain, jos kohdetietokanta vastaa edelleen odotettua reaaliaikaista tilannevedosta. Tämä on hyödyllistä, kun yhdistämissuunnitelma on tarkistettu aiemmin ja reaaliaikaiset rivit ovat saattaneet muuttua ennen käyttöönottoa.
Tavallisessa asetelmassa hiekkalaatikon muokkaukset siirretään reaaliaikaiseen tietokantaan. Pohja on reaaliaikainen tietokanta sillä hetkellä, kun hiekkalaatikko kopioitiin siitä, meidän-puoli on muokattu hiekkalaatikko ja heidän-puoli on reaaliaikainen tietokanta nykytilassaan. Kohteena on reaaliaikainen tietokanta, joten odotettu reaaliaikainen tilannevedos on theirs, ja kirjoitettavat operaatiot ovat niitä, joita reaaliaikaisessa tietokannassa ei vielä ole (katso Operaatioden valinta).
use Merql\Connection;
use Merql\Merql;
use Merql\Plan\OperationSelection;
use Merql\Plan\SelectedMergeResultFactory;
use Merql\Snapshot\SnapshotStore;
Merql::init(Connection::sqlite('/data/live.sqlite'));
$plan = Merql::plan('promote-1', 'base', 'ours', 'theirs');
// Skip rows with unresolved conflicts.
$conflicted = [];
foreach ($plan->conflicts as $conflict) {
$conflicted[$conflict->table . "\0" . $conflict->rowKey] = true;
}
$ids = [];
foreach ($plan->operations as $operation) {
$missing = $operation->source === 'ours'
|| ($operation->source === 'merged' && $operation->type === 'update');
if ($missing && !isset($conflicted[$operation->table . "\0" . $operation->rowKey])) {
$ids[] = $operation->id;
}
}
$selected = (new SelectedMergeResultFactory())->fromOperationSelection(
$plan,
OperationSelection::fromIds($ids),
SnapshotStore::load('base'),
);
$applied = Merql::applyGuarded($selected, SnapshotStore::load('theirs'));
if ($applied->hasErrors()) {
foreach ($applied->errors() as $error) {
echo $error . "\n";
}
}
Merql::applyGuarded() kirjoittaa tietokantaan, joka välitetään funktiolle Merql::init(). Odotetun reaaliaikaisen tilannevedoksen on kuvattava samaa tietokantaa: ota se kohteesta ja riittävän hiljattain, jotta ehdot ovat mielekkäitä.
Ehdot
Suojattu SQL lisää luotuihin lausekkeisiin reaaliaikaisia rivejä koskevat ehdot:
- päivityksissä kohderivin identiteetin on oltava olemassa ja muiden kuin identiteettisarakkeiden arvojen on vastattava odotettua reaaliaikaista riviä,
- poistoissa kohderivin identiteetin on oltava olemassa ja muiden kuin identiteettisarakkeiden arvojen on vastattava odotettua reaaliaikaista riviä,
- lisäyksissä kohteen identiteetti ei saa olla jo olemassa.
Jos jokin lauseke vaikuttaa nollaan riviin, merql käsittelee suunnitelmaa vanhentuneena. Tapahtuma perutaan, ja palautettava ApplyResult sisältää virheen Optimistic precondition failed for guarded merge statement.
MySQL-ajurissa päivitys, jonka arvot vastaavat jo reaaliaikaista riviä, vaikuttaa myös nollaan riviin, koska MySQL laskee muuttuneet rivit eikä täsmänneitä rivejä. Tällainen päivitys epäonnistuu vanhentuneena, vaikka rivi täsmää (#2).
SQLite laskee täsmänneet rivit ja hyväksyy sen. Näin voi käydä merged-päivityksessä, kun molemmat puolet ovat tehneet samaan riviin saman muutoksen.
Operaatioiden valinta
Yhdistämistulos sisältää molempien puolten operaatiot, koska se muuttaa pohjatilan yhdistetyksi tilaksi. Kun tulos otetaan käyttöön kohteessa, jossa on jo heidän-puolen tila, heidän-puoleltaan peräisin olevat operaatiot kuvaavat muutoksia, jotka kohteessa ovat jo, joten niiden ehdot epäonnistuvat:
| Operaatio | Tila kohteessa, jossa on heidän-puolen tila | Valitse |
|---|---|---|
ours lisäys, päivitys tai poisto |
Puuttuu | Kyllä |
merged päivitys (molemmat puolet muuttivat riviä) |
Sisältää heidän sarakkeensa, meidän sarakkeet puuttuvat | Kyllä |
theirs lisäys |
Rivi on olemassa, joten suojattu lisäys vaikuttaa nollaan riviin | Ei |
merged poisto (molemmat puolet poistivat rivin) |
Rivi on poistettu, joten suojattu poisto vaikuttaa nollaan riviin | Ei |
theirs päivitys tai poisto |
Jo käytössä | Ei |
Siksi koko tuloksen Merql::merge() välittäminen funktiolle applyGuarded() epäonnistuu heti, kun heidän-puolensa on lisännyt rivin tai molemmat puolet ovat poistaneet rivin. Valitse ensin operaatiot lähteen perusteella yllä kuvatulla tavalla tai luomalla ChangeGroupSelection tarkistuksen UI-tuloksen pohjalta. Jätä pois kohteessa $plan->conflicts luetellut rivit: valittu tulos on aina puhdas, ja ristiriitaisen rivin operaatio sisältää meidän arvomme ristiriitaisessa sarakkeessa (katso Yhdistämissuunnitelmat).
Valikoitu käyttöönotto
Suojattu käyttöönotto toimii yhdistämissuunnitelmasta luotujen valittujen yhdistämistulosten kanssa, myös muutosryhmän perusteella tehtyjen valintojen kanssa.
use Merql\Plan\ChangeGroupSelection;
use Merql\Plan\SelectedMergeResultFactory;
use Merql\Snapshot\SnapshotStore;
$selection = ChangeGroupSelection::fromIds([$plan->changeGroups[0]->id]);
$selected = (new SelectedMergeResultFactory())->fromChangeGroupSelection(
$plan,
$selection,
SnapshotStore::load($plan->baseSnapshot),
);
$applied = Merql::applyGuarded($selected, SnapshotStore::load($plan->theirsSnapshot));
Tämän ansiosta isäntäsovellus voi ottaa käyttöön osan tarkistetuista ryhmistä ja samalla varmistaa, etteivät reaaliaikaiset rivit ole poikenneet suunnitelman luonnin jälkeen.
SQL-esikatselu
Käytä toimintoa SqlGenerator::generateGuarded() suojattujen lausekkeiden tarkasteluun suorittamatta niitä.
use Merql\Apply\SqlGenerator;
use Merql\Snapshot\SnapshotStore;
$statements = SqlGenerator::generateGuarded(
$selected,
SnapshotStore::load($plan->theirsSnapshot),
);
foreach ($statements as $statement) {
echo $statement['sql'] . "\n";
}
Luodut lausekkeet ovat yhä parametrisoituja. Päivitysten ja poistojen ehdot ilmaistaan ylimääräisillä WHERE-lauseilla ja lisäysten ehdot NOT EXISTS-tarkistuksilla.
Suojattu tai tavallinen käyttöönotto
Merql::apply() suorittaa samat operaatiot ilman ehtoja. Päivitykset ja poistot onnistuvat tällöin riippumatta siitä, onko reaaliaikainen rivi muuttunut suunnitelman luonnin jälkeen. Olemassa olevan rivin lisäys epäonnistuu tietokannan kaksoisavainvirheeseen. Käytä tavallista käyttöönottoa kohteessa, jonka tiedät olevan yhä pohjatilassa, ja suojattua käyttöönottoa, kun muut kirjoittajat ovat voineet muuttaa kohdetta tilannevedoksen ottamisen jälkeen.