Korumalı Uygulama
GuardedApplier, temiz bir MergeResult öğesini yalnızca hedef veritabanı beklenen canlı anlık görüntüyle hâlâ eşleşiyorsa uygular. Bu, birleştirme planı daha önce incelendiğinde ve uygulamadan önce canlı satırlar değişmiş olabileceğinde kullanışlıdır.
Tipik kurulumda bir sanal alanın düzenlemeleri canlı veritabanına aktarılır. Taban, sanal alanın kopyalandığı andaki canlı durumdur; ours düzenlenen sanal alandır, theirs ise canlı veritabanının şu anki durumudur. Hedef canlı veritabanı olduğundan beklenen canlı anlık görüntü theirs değeridir; yazılacak işlemler ise canlıda henüz bulunmayanlardır (bkz. İşlemleri seçme).
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(), Merql::init() öğesine iletilen veritabanına yazar. Beklenen canlı anlık görüntü aynı veritabanını açıklamalıdır: hedef veritabanından alın ve önkoşulların anlamlı olması için yeterince yakın zamanda oluşturun.
Önkoşullar
Korumalı SQL, oluşturulan ifadelere canlı satır önkoşulları ekler:
- güncellemeler, hedef satır kimliğinin var olmasını ve kimlik dışı sütun değerlerinin beklenen canlı satırla eşleşmesini gerektirir,
- silmeler, hedef satır kimliğinin var olmasını ve kimlik dışı sütun değerlerinin beklenen canlı satırla eşleşmesini gerektirir,
- eklemeler, hedef kimliğin henüz var olmamasını gerektirir.
Herhangi bir ifade sıfır satırı etkilerse merql planı eski kabul eder. İşlem geri alınır ve döndürülen ApplyResult, Optimistic precondition failed for guarded merge statement. hatasını içerir
MySQL üzerinde, değerleri canlı satırla zaten eşleşen bir güncelleme de sıfır satırı etkiler; çünkü MySQL, eşleşen satırları değil değişen satırları sayar. Dolayısıyla satır eşleşse bile güncelleme eski olarak başarısız olur (#2). SQLite eşleşen satırları sayar ve bunu kabul eder. Bu, her iki tarafın da bir satırda aynı değişikliği yaptığı merged güncellemesinde görülebilir.
İşlemleri seçme
Birleştirme sonucu, tabanı birleştirilmiş duruma dönüştürdüğü için her iki tarafın işlemlerini içerir. Zaten theirs durumunu tutan bir hedefe uygulandığında, theirs tarafından gelen işlemler hedefin zaten sahip olduğu değişiklikleri tanımlar ve bu işlemlerin önkoşulları başarısız olur:
| İşlem | theirs durumunu tutan hedefteki durum | Seç |
|---|---|---|
ours ekleme, güncelleme veya silme |
Eksik | Evet |
merged güncelleme (iki taraf da satırı değiştirdi) |
theirs sütunları var, ours sütunları eksik | Evet |
theirs ekleme |
Satır var; korumalı ekleme bu yüzden sıfır satırı etkiler | Hayır |
merged silme (iki taraf da satırı sildi) |
Satır yok; korumalı silme bu yüzden sıfır satırı etkiler | Hayır |
theirs güncelleme veya silme |
Zaten uygulandı | Hayır |
Merql::merge() öğesinin tüm sonucunu applyGuarded() öğesine iletmek, theirs bir satır eklediğinde veya iki taraf da bir satırı sildiğinde başarısız olur. Önce yukarıdaki gibi kaynağa göre veya bir inceleme UI öğesinden oluşturulan ChangeGroupSelection ile işlemleri seçin. $plan->conflicts içinde listelenen satırları dışarıda bırakın: seçili sonuç her zaman temizdir ve çakışan bir satıra ait işlem, çakışan sütunda ours değerini taşır (bkz. Birleştirme Planları).
Seçili Uygulama
Korumalı uygulama, değişiklik grubuna göre yapılan seçimler de dahil olmak üzere birleştirme planından üretilen seçili birleştirme sonuçlarıyla çalışır.
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));
Bu, bir ana uygulamanın incelenmiş grupların bir alt kümesini aşamalamasına ve plan oluşturulduktan sonra canlı satırların değişmediğini doğrulamasına olanak tanır.
SQL Önizlemesi
Korumalı ifadeleri yürütmeden incelemek için SqlGenerator::generateGuarded() kullanın.
use Merql\Apply\SqlGenerator;
use Merql\Snapshot\SnapshotStore;
$statements = SqlGenerator::generateGuarded(
$selected,
SnapshotStore::load($plan->theirsSnapshot),
);
foreach ($statements as $statement) {
echo $statement['sql'] . "\n";
}
Oluşturulan ifadeler yine parametrelidir. Önkoşullar, güncelleme ve silmeler için ek WHERE koşullarıyla, eklemeler içinse NOT EXISTS denetimleriyle belirtilir.
Korumalı veya normal uygulama
Merql::apply(), aynı işlemleri önkoşullar olmadan yürütür. Böylece canlı satır plan oluşturulduğundan beri değişmiş olsun ya da olmasın güncellemeler ve silmeler başarılı olur; mevcut bir satırı ekleme girişimi ise veritabanının yinelenen anahtar hatasıyla başarısız olur. Hedefin hâlâ tabanı tuttuğunu bildiğinizde normal uygulamayı, anlık görüntüsü alındıktan sonra hedefe başka yazma işlemleri yapılmış olabileceğinde korumalı uygulamayı kullanın.